Live data from Hacker News

Some Obscure C Features

multun.net

61–70 of 147 posts

Re: Some Obscure C Features

#61
post #52

A little off-topic but here is a cool piece of code about a special case in C: void (*foo)() = 0; void (*bar)() = (void *)0; void (*baz)() = (void *)(void *)0; // Error Can you guess why compilers reject the last line?

Only the first two expressions on the right are null pointer constants (integral constant expression with a value of 0, optionally cast as a void *), that can be used to initialize all pointer variables, including function pointers. The last one is merely a null pointer (to void), that can't be implicitly converted to a pointer to a function.

C++ has stricter rules for null pointer constants, and thus only the first version is valid C++.

Re: Some Obscure C Features

#63
post #59
post #58

Earlier quoted context omitted.

The comma operator isn’t very obscure at all. Even JS has it.

It's not the comma operator that is being noted as obscure, but particular usage of it, such as complex return statements that set a value and return another.

Right, that’s also the case for comma in JS.

Re: Some Obscure C Features

#64
post #56
post #43

All craziness but then: >a[b] is literally equivalent to *(a + b). Is this obscure? I thought that's pretty much the first thing you learn about arrays in C? It's pointers, all the way down.

Not really. The way it's usually introduced is that you get the same "reference" both ways. The fact that it's literally equivalent, and especially that there's no pointer type requirement on the left-hand-side, with the consequence of allowing ridiculous code like 2[array], is pretty obscure. Even more so because the equivalence doesn't work that way in C++ -- in general, features of C that aren't available in C++ t…

>Even more so because the equivalence doesn't work that way in C++

What do you mean? As far as I remember, C++ is very similar in this respect when it comes to array and pointer types.

Re: Some Obscure C Features

#65
post #63
post #59

Earlier quoted context omitted.

It's not the comma operator that is being noted as obscure, but particular usage of it, such as complex return statements that set a value and return another.

Right, that’s also the case for comma in JS.

I reckon that most language with grammar inspired in C describes the comma operator.

Re: Some Obscure C Features

#66

Most of these are due to the cruft added in C99 and later. Compile-time trees are possible without compound literals. More than twenty years ago, I made a hyper-linked help screen system a GUI app whose content was all statically declared C structures with pointers to each other. At file scope, you can make circular structures, thanks to tentative definitions, which can forward-declare the existence of a name, whose…

Also variable assignment with identifier list:

   a = 0;
   x = (type_t) { .y = a++, .x = a++ }
Now, figure it out the order of the field's assignment.

Re: Some Obscure C Features

#67

In numerical analysis, "Hexadecimal float with an exponent" is not an obscure feature, it's a really nice one! If you want to communicate to somebody an exact number that your program has output, you need to either tell them the decimal number to enough digits + the number of digits (i.e., "Float32(0.1)", which is distinct from "Float64(0.1)"), or you can tell them the same number in full precision in binary, in whic…

Also, the printf can be used to display floating point in hexadecimal notation.

The printf specifiers:

  %e Scientific notation           3.9265e+2
  %a Hexadecimal floating point -0xc.90fep-2

Re: Some Obscure C Features

#68
post #63
post #59

Earlier quoted context omitted.

It's not the comma operator that is being noted as obscure, but particular usage of it, such as complex return statements that set a value and return another.

Right, that’s also the case for comma in JS.

So, are you making the case that the examples present are common in JS as well? Because the whole point of the comment was in the uncommon usage of comma operator, as stated in the first sentence.

And to be clear, even if it is common in JS, that still doesn't reduce the usefulness of the original comment, because we aren't talking about JS, we're talking about C, and the commonness of the features notes in the C ecosystem. There are plenty of obscure oft-ignored features on one language that are common in another. For example, taking someone's interesting C macro that allows some level of equivalence to functional map and apply and saying "that isn't very obscure, even lisp has that" is missing the point.

Re: Some Obscure C Features

#69
post #52

A little off-topic but here is a cool piece of code about a special case in C: void (*foo)() = 0; void (*bar)() = (void *)0; void (*baz)() = (void *)(void *)0; // Error Can you guess why compilers reject the last line?

[deleted]

Re: Some Obscure C Features

#70

Most of these are due to the cruft added in C99 and later. Compile-time trees are possible without compound literals. More than twenty years ago, I made a hyper-linked help screen system a GUI app whose content was all statically declared C structures with pointers to each other. At file scope, you can make circular structures, thanks to tentative definitions, which can forward-declare the existence of a name, whose…

Also variable assignment with identifier list: a = 0; x = (type_t) { .y = a++, .x = a++ } Now, figure it out the order of the field's assignment.

The order of evaluation among initializers is unspecified, which makes it UB.

We don't have to use mixed-up designated initializers to run aground. Just simply:

  { int a = 0;
    int x[2] = { a++, a++ }; }
This was also new in C99 (not to mention the struct literal syntax); in C90, run-time values couldn't be used for initializing aggregate members, so the issue wouldn't arise.

Code like:

   { int a = 0;
     struct foo f = { a, a }; }
was supported in the GNU C dialect of C90 before C99 and of course is also a long-time C++ feature.

https://gcc.gnu.org/onlinedocs/gcc/Initializers.html#Initial...

The doc doesn't say anything about order. I can't remember what C++ has to say about this.

Post reply on HN