Live data from Hacker News

Some Obscure C Features

multun.net

81–90 of 147 posts

Re: Some Obscure C Features

#81
I was reading the source code for a NES assembler written in pre-C99 C, and there was an odd C feature used in it that I haven't really seen anywhere else.

It was before C had built-in booleans and the author had defined their own, but true was:

    void * true_ptr  = &true_ptr;
true_ptr is a pointer to itself. So however many times you deference it:

    printf("%p\n", true_ptr);
    printf("%p\n", &true_ptr);
    printf("%p\n", *((void**)true_ptr));
    printf("%p\n", *((void**)*((void**)true_ptr)));
You get the same pointer:

    0x5555fefe715b
    0x5555fefe715b
    0x5555fefe715b
    0x5555fefe715b
I still think that it's neat that, even with ASLR, you have an address at compile time that you know won't collide with address space of malloc results, or the address space of your stack.

Also you can declare the pointer as const and the value it points to as const and, if your kernel faults on writing to readonly memory pages, you get a buggier version of a NULL pointer that only segfaults on write.

Also it takes a second to figure out why the position of the const matters even though the pointer's value is the value of the pointer, and why only one of these segfaults on write:

    const void * const_pointer = &const_pointer;
    void * const const_value   = &const_value;

Re: Some Obscure C Features

#82

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…

I wish Javascript, etc. had hexadecimal floats. It’s annoying to worry about whether different implementations might parse your numbers differently, worrying about whether you need to write down 15 or 17 decimal digits, ... Often the numbers (e.g. coefficients of some degree 10 polynomial approximation of a special function) are not intended to be human-readable anyway. Such values were typically computed in binary i…

I mean, it's not too difficult to add them. You can parse, shove your result into a data view, Uint32Array, or whatever, then turn that into a Float64Array.

Re: Some Obscure C Features

#83
post #81

I was reading the source code for a NES assembler written in pre-C99 C, and there was an odd C feature used in it that I haven't really seen anywhere else. It was before C had built-in booleans and the author had defined their own, but true was: void * true_ptr = &true_ptr; true_ptr is a pointer to itself. So however many times you deference it: printf("%p\n", true_ptr); printf("%p\n", &true_ptr); printf("%p\n", *((v…

I've used this feature to create constants that are unique IDs.

Re: Some Obscure C Features

#86
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.

Agreed, and I never made the connection that array[index] could be written as index[array] haha.

Only if index and array have the types of same size. Because pointer arithmetic works in terms of object sizes, not in individual bytes.

Re: Some Obscure C Features

#87

Earlier quoted context omitted.

Agreed, and I never made the connection that array[index] could be written as index[array] haha.

Only if index and array have the types of same size. Because pointer arithmetic works in terms of object sizes, not in individual bytes.

  foo[3]
  *(foo + 3)
  *(3 + foo)
  3[foo]
They all do the same thing.

Re: Some Obscure C Features

#88
post #64
post #56

Earlier quoted context omitted.

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.

Only for the most primitive types, though. For anything else, operator[] is used in C++ instead, without an operator+ fallback. So for example, if your array is a std::array instead of a C-style array, saying 1[array] will not work.

Re: Some Obscure C Features

#89

The article has examples of array parameters like int b[const 42][24][*] but you can get more fun with variably modified array parameters instead of just constants like 42. For example, double sum_a_weird_shaped_matrix(int n, double array[n][3*n]) { double total = 0; for (int x = 0; x has a variable and a more complicated expression in those positions. But those variably modified parameters can have arbitrary express…

Another neat note IIRC is that array parameter sizes don't actually do anything, they just are there for semantic purposes and get treated as raw pointers. So if you do void func(int x[10]); You're free to call it like int k[5]; func(k); And you won't get any warnings. Unsettling!

That's what the static keyword means in those array declarators.

    void func(int x[static 10]);
must be called with an argument that is a pointer to the start of a big enough array of int. I can't get recent GCC or Clang to warn on violations of this, though.

Re: Some Obscure C Features

#90

Earlier quoted context omitted.

I wish Javascript, etc. had hexadecimal floats. It’s annoying to worry about whether different implementations might parse your numbers differently, worrying about whether you need to write down 15 or 17 decimal digits, ... Often the numbers (e.g. coefficients of some degree 10 polynomial approximation of a special function) are not intended to be human-readable anyway. Such values were typically computed in binary i…

I mean, it's not too difficult to add them. You can parse, shove your result into a data view, Uint32Array, or whatever, then turn that into a Float64Array.

Fair enough. You can also just base64-encode (or whatever) a big block of binary data. But having built-in support for hex floats would be nicer.
Post reply on HN