For the best experience on desktop, install the Chrome extension to track your reading on news.ycombinator.com
Hacker Newsnew | past | comments | ask | show | jobs | submit | history | more gallier2's commentsregister

If it is only the tone that bothers you, maybe you should abstain from programming C. ;-)


First tone then content...


No, version control is not simple, never was. git was the first vcs that didn't suck because it was the first tool that understood the nature of the problem. All others were ass backward and instead of solving the problem stood in the way and actively made things worse.


The only visual git tool I really like is gitextensions for windows.


Fork has its advantages too (and a slicker UI if that matters for you)


and the ultimate option for git lg is --reflog. Seeing all branches, even the old ones that do not exist anymore is a eye opening event in discovering the true nature of git: it never changes a commit, ever.


While reflog is amazing, the "ever" in your statement is not true, `git gc` will prune your reflog: https://git-scm.com/docs/git-gc

Most of the time this doesn't matter in practice but you should be aware that unreachable refs don't stay around forever.


In most places it uses int for string and buffer sizes lengths. It wouldn't surprize me if 2GiB of data could trigger several overflows.


DSP's have often uncommon sizes. tms320c5502 for example has following sizes: char-- 16 bits short --16 bits int --16 bits long-- 32 bits long long -- 40 bits float-- 32 bits double -- 64 bits


Indeed. The C28x line by the same company shares CHAR_BIT == 16 with C55. C28x is quite popular in power electronics applications.

"Relevant" is in the eyes of the beholder, and its all too easy to no-true-scotsman your way out of existing architectures. I claim that both of these architectures are relevant by virtue of suppliers continuing to make new chips that use them, and system builders continuing to select those chips in new products.


> 40 bits float-- 32 bits double

Isn't double required to have more precision than float?


I think their formatting got swallowed by HN:

char-- 16 bits

short --16 bits

int --16 bits

long-- 32 bits

long long -- 40 bits

float-- 32 bits

double -- 64 bits


> long long -- 40 bits

Isn't this in direct contradiction to what the article says?

> long long: At least 64 bits, and at least as wide as long.


The XOR trick has also the disadvantage of being 3 dependend instructions that can not overlap. The one with a temp variable has only 2 of them dependend and can therefore save one cycle on an OO CPU.


Even in a old OOO core because of register renaming and friends the swap could have a latency of zero in the first place.


Foreach macros. Nice when you have a list of constant that you need for declaring a lot of tables or enumerations. Here an example with ISO-639 language codes

Example with 3 "values". This is the base definition from which all the tables and enums are produced.

  #define FOREACH_LAN(LAN)\
    LAN(GA, IE, C_ANSI    )  /**< Irish Gaelic   :  0 */ \
    LAN(DE, DE, C_ANSI    )  /**< German         :  1 */ \
    LAN(DA, DA, C_ANSI    )  /**< Danish         :  2 */ \
    LAN(EL, EL, C_GREEK   )  /**< Greek          :  3 */ \
    LAN(EN, GB, C_ANSI    )  /**< English        :  4 */ \
    LAN(ES, ES, C_ANSI    )  /**< Spanish        :  5 */ 
   etc.
Let's define an enum indexing with these languages

    #define GENERATE_LANIDX(lan,country,codepage) LANIDX_ ## lan,

    typedef enum {
      LANIDX_UNDEFINED = -1,        // 
      
    FOREACH_LAN(GENERATE_LANIDX)  

      LANIDX_MAX                    // Automatically get the upper bound
    } LANIDX_TYPE;
This is equivalent to

    typedef enum {
      LANIDX_UNDEFINED = -1,        // 
      LANIDX_GA,      
      LANIDX_DE,      
      LANIDX_DA,      
      LANIDX_EL,      
      LANIDX_EN,      
      LANIDX_ES,      
      LANIDX_MAX                    // Automatically get the upper bound
    } LANIDX_TYPE;
but I didn't need to repeat all the language codes, the macro did it for us.

Now in the module I can define tables, also without needing to repeat the codes

   const char *LanIdx2LanTable[] = {
    #define GENERATE_LANIDDX_2_LAN(lan,country,codepage)  [1+ LANIDX_ ## lan]={#lan},
    FOREACH_LAN(GENERATE_LANIDDX_2_LAN)
   };

   const char *LanIdx2CodePageTable[] = {
     #define GENERATE_LANCP(lan,country,codepage)  [1+LANIDX_ ## lan]=codepage,
     FOREACH_LAN(GENERATE_LANCP)
   };


Rarely used feature that I quite like is defining function types.

   typedef bool foo_fn(int, char);
This declares a type of a function.

   foo_fn  foo1, foo2, foo3, foo4;
This declares 4 functions of the same type. It's equivalent to

   bool foo1(int, char);
   bool foo2(int, char);
   bool foo3(int, char);
   bool foo4(int, char);
Unfortunately the type can not be used at function definition but that is not where function are interesting. They are neat for function pointers especially those that require casting.

   void function_taking_foo(int, foo_fn *);

   function_taking_foo(1, foo1);   // no cast necessary as type is identical and even
instead of

   function_taking_foo(1, (bool(*)(int,char))foo1);
When you have a lot function pointers it is incredibly more readable than the usual syntax.


The question is also to consider when and at what price. A Amiga 2000 had indeed quite the extension possibilities, but they were expensive. An Amiga 500 was a whole other story. The expandibility was limited and only in later times was it possible to add a lot of RAM and disks, etc. and RAM it needed a lot, much more than than Atari, but the Ataris didn't need as much memory, but they were also less greedy with it.


Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search:

HN For You