HNHacker News
TopNewBestAskShowJobs

gallier2

139 karma · joined January 7, 2020

submissionscomments
gallier2··on Comp.lang.c Frequently Asked Questions
If it is only the tone that bothers you, maybe you should abstain from programming C. ;-)
gallier2··on New in Git: switch and restore
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.
gallier2··on New in Git: switch and restore
The only visual git tool I really like is gitextensions for windows.
gallier2··on New in Git: switch and restore
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.
gallier2··on Althttpd: Simple webserver in a single C file
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.
gallier2··on Summary of C/C++ integer rules
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
gallier2··on That XOR Trick (2020)
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.
gallier2··on What is your favorite C programming trick? (2009)
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)
   };
gallier2··on What is your favorite C programming trick? (2009)
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.
gallier2··on Really Atari ST?
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.
gallier2··on Really Atari ST?
Indeed. As a student (1987) I had an Amiga 500 and after a few months I sold it and bought an Atari Mega ST2 in its place. The Amiga was so unpleasant to use for programming. To be confortably usable it required at least 2 floppy drives (a 3rd one would even been useful) or a hard drive, expanding beyond 1 MB was also not cheap and the display was horrible. TV resolution 576i (PAL) is inadequate for editing text. On the Atari we had the cheap SM-124 fantastic monochrome 71Hz refresh rate screen which allowed to stay for hours programming. All compilers and editor I needed would fit in one 800K floppy and the 2 mb of RAM would even allow to work from RAM disk. A breeze. Gaming was still possible with the second cable connected to the TV set (later I installed the PC-Speed emulator in my Mega ST which transformed it in a very capable XT PC (8Mhz V30, 704 kB DOS memory, with 640x400 Olivetti graphics). The Amiga was better for gaming, no contest, for serious stuff like porgramming, word processing (pixel perfect Signum!) and stuff, it was so much better in lower budget.
gallier2··on Really Atari ST?
Atari STE had 2 channels 8 bit DAC à 25kHz on DMA.

It was the Falcon who had incredible sound capacity with its matrix channel mixer and DSP.

gallier2··on C’s Biggest Mistake (2009)
Did you see that the article is from 2009?
gallier2··on AVX-512 Mask Registers, Again
The D language still gives access to x87 code. The language defines a type called real which is supposed to give access to the highest precision the implementation allows, on x86 it is the x87 with its 80 bits. On other platforms it's 64 bits or 128 bits. float and double have defined sizes.
gallier2··on Better C – A subset of D Programming Language
> A type is much denser, than a textual description, and in most >cases sufficient.

In feeble languages with simpleton typesystem may be, but in highly generic templated language like D it is not the case. The type is not dense at all.

What's funny is that in general people complain that compiler errors in D are unreadable. You know why they are unreadable?

Because they print out the types of the functions in which the error occurs and that is nothing more than word salad for generic functions.

Types with hundreds of characters are very common.

gallier2··on Better C – A subset of D Programming Language
> because being able to write down types is really quite important to me.

The issue arises only with generic heavily templated functions. Nothing in D forbids you to write your programs with all types explicitly written down. That's btw how I mostly write my code.

gallier2··on Better C – A subset of D Programming Language
> The language needs fixed so it can express its own types.

The language expresses its types just fine (it's in the mangled name in the object file). The issue is that there is no point in the human readable form of these types.

gallier2··on Better C – A subset of D Programming Language
> That should not be a problem. It is a problem in D because of a lacking in D.

It is not a problem, the compiler copes with it. The problem comes from the fact that such a type is absolutely not interesting to know how it is written. The unmangled type is unreadable.

gallier2··on Better C – A subset of D Programming Language
No. It is known at compile time.

Template declarations in D take 2 parameter lists. The first is the template parameters the second the runtime parameter: in auto whatDoesItReturn(int i)() { static if (i == 0) { return int.init; } else { return string.init; } }

we have (int i) as template parameter and () as an empty runtime parameter. In C++ syntax whatDoesItReturn<int i>()

at instanciation the syntax is different:

whatDoesItReturn!0() will instantiate a function returning an int

whatDoesItReturn!42() will instantiate a function returning a string.

gallier2··on A primer on some C obfuscation tricks
No need for that, any Rust program is obfuscated.
gallier2··on A primer on some C obfuscation tricks
The initial intent was to add 2 hex values, but using 0xfffe tripped the parser.
gallier2··on A primer on some C obfuscation tricks
clang will warn as it doesn't like int+string constructs.

&"Yes\0No"[!x>>2]; // same number of characters

to shut it up.

gallier2··on A primer on some C obfuscation tricks
!!x is idiomatic. (bool) cast is modern.

I use !=0 in only one context, if(strcmp(a,b) != 0) to check if two strings differ. Normally if an if() expression I don't check explicitly for 0 or not 0, except for strcmp class of functions, because of the ordered comparison of it (<0, 0, >0) , its "boolean" value is inverted, so somewhat counter intuitive if used with implicit boolean values.

gallier2··on A primer on some C obfuscation tricks
You can also typecast to bool since C99. (bool)x if you include <stdbool.h> or (_Bool) if not.
gallier2··on A primer on some C obfuscation tricks
because ternary operation is a Rvalue only in C. In C++ and as gcc extension it can be used as Lvalue, but not in regular plain C.
gallier2··on Wc in D: 712 Characters Without a Single Branch
You can also write verbose code in D. The language doesn't prohibit it.
gallier2··on Is Git Irreplaceable? (2019)
git log --reflog --all

is the more important imo than

git reflog

gallier2··on Is Git Irreplaceable? (2019)
NO. Nothing is gone after commit. You just don't see it.

Make a git log --reflog --all and you will see all the commits you made (or rebase made) in the last 3 months.

You can than rescucitate an old branch by simply putting a branch name on it with git branch newname <old sha1>

gallier2··on Is Git Irreplaceable? (2019)
You have a branch named <branchname> you do your operation that fouls up your branch. If you check with

git log --reflog --all

you will see with this magical command that git DOESN'T REMOVE any commit. Your old tree is still there, only normally hidden. The commit that was there before you fouled up your branch is still there.

You now only need to set your branch to the old commit. A branch is nothing else than a pointer in the tree.

You have 2 possiblities to change the commit a branch points to

1. git branch --force <branchname> SHA1 (works only if <branchname> is not the current checked-out branch. Simply checking out with the SHA1 works also as it deteches the HEAD).

2. replace the SHA1 in the text file in .git/refs/heads/<branchname> by the SHA1 where you want the branch to point to.

With that, your repo is in the same state it was before your error.

gallier2··on Let the Compiler Do the Work
Since C11 there's _Generic which allows to do it. Using macros in that case is strongly advised (or else it would be very verbose).
← PreviousPage 2 of 2