News for hackers. Stuff that matters.
Re:The Descent to C (2013) by smcameron on Friday September 03, 2021 @09:27AM (#28403906)
> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).)

To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write

     i[array]
and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)"

But nobody really does that, because that would be kind of insane.

Re:The Descent to C (2013) by unwind on Friday September 03, 2021 @09:35AM (#28404003)
Once the point is home, you can drive it a little bit more by exploiting the fact that string literals can be converted to pointers to the first characters, and do

    putc(2["ABCDEF"], stdout);
This prints 'C'.
Re:The Descent to C (2013) by dankoncs on Friday September 03, 2021 @01:18PM (#28406874)
int const* const x; // C

int const& x; // C++

A reference is functionally equivalent to a const pointer. (Reference reassignment is disallowed. Likewise, you cannot reassign a const pointer. A const pointer is meant to keep its pointee [address].) The difference between them is that C++ const references also allow non-lvalue arguments (temporaries).

It is much easier to read from right to left when decoding types. Look for yourself:

- double (* const convert_to_deg)(double const x) // const pointer to function taking a const double and returning double

- int const (* ptr_to_arr)[42]; // pointer to array of 42 const ints

- int const * arr_of_ptrs[42]; // array of 42 pointers to const ints

- int fun_returning_array_of_ints()[42];

Try it out yourself: https://cdecl.org/

Hence, I am an "East conster". (Many people are "West consters" though.)

You can return function pointers:

typedef struct player_t player_t; // let it be opaque ;)

int game_strategy1(player_t const * const p)

{

    /* Eliminate player */

    return 666;
}

int game_strategy2(player_t const * const p)

{

    /* Follow player */
    
    return 007;
}

int (* const game_strategy(int const strategy_to_use))(player_t const * const p)

{

    if (strategy_to_use == 0)
        return &game_strategy1;

    return &game_strategy2;
}

Functional programming = immutable (const) values + pure functions (no side effects).

Consting for me is also a form of documentation/specification.

"East const" for life! :)

Re:The Descent to C (2013) by harry8 on Friday September 03, 2021 @02:20PM (#28407538)
10 or 42?
Re:The Descent to C (2013) by danielozcpp on Friday September 03, 2021 @02:23PM (#28407568)
Thank you. 42. I edited my comment above.
Re:The Descent to C (2013) by lifthrasiir on Friday September 03, 2021 @12:28PM (#28406285)
If array were, say, uint32_t* then what `*(array + i)` would do is actually `(intptr_t)array + i * 4` and not `(intptr_t)array + i`. If array were uint16_t* then it's `(intptr_t)array + i * 2`. In short the way the pointer arithmetic gets translated greatly depends on the type of the pointee and thus is not as primitive as it can be.
Re:The Descent to C (2013) by kzrdude on Friday September 03, 2021 @12:46PM (#28406515)
I think it depends on the coder if it makes more sense to them to write out the scale by element size or not. For me, the `+` is just pointer arithmetic and of course an addition in number of elements (so I don't think of the scaling at all).

Just saying that "actually it's just array + i" makes more sense - for me(!).

Re:The Descent to C (2013) by Zababa on Friday September 03, 2021 @06:30PM (#28410135)
This is actually a really good way to drive home that arrays don't really "exists" in C and are just syntaxic sugar for pointer arithmetic.
Re:The Descent to C (2013) by kevin_thibedeau on Friday September 03, 2021 @10:20PM (#28411512)
They exist in the sense that their length is sometimes known if the full definition is visible. sizeof(array) isn't the same as sizeof(generic ptr to array).
Re:The Descent to C (2013) by sn41 on Friday September 03, 2021 @10:29PM (#28411572)
This is not entirely a complete view. For example, sizeof() operator returns the declared size of an array. It seems that C recognizes the concept of an array.
Re:The Descent to C (2013) by omegalulw on Friday September 03, 2021 @08:10PM (#28410869)
"Because real programmers only need void*".
Re:The Descent to C (2013) by Zababa on Saturday September 04, 2021 @05:51AM (#28413629)
There's a language for that https://github.com/kyouko-taiga/void-lang
Re:The Descent to C (2013) by a3n on Friday September 03, 2021 @06:18PM (#28410039)
This sub-thread is better than a Vim thread. :)
Re:The Descent to C (2013) by brundolf on Saturday September 04, 2021 @01:06PM (#28416835)
The OP probably doesn't want people to run away and never look back
Re:The Descent to C (2013) by lebuffon on Friday September 03, 2021 @12:46PM (#28406514)
Interesting. Looks like Forth. :-)
Re:The Descent to C (2013) by travelbuffoon on Friday September 03, 2021 @12:18PM (#28406180)
Speaking of such funny business: unfortunately I have seen *(array + i) quite a few times.

To make it worse, it’s in a parser for external data in binary format, where you really shouldn’t be playing funny tricks.

Re:The Descent to C (2013) by bachmeier on Friday September 03, 2021 @11:37AM (#28405596)
> nobody really does that, because that would be kind of insane

Yeah. That's why people don't do things in C. It's more like most C programmers probably weren't aware of this. After your comment, we'll start to see C codebases everywhere with that.

Re:The Descent to C (2013) by LeifCarrotson on Friday September 03, 2021 @12:17PM (#28406167)
Most programmers probably weren't aware of this, but no true Scottish C programmer would be unaware of it.

If you want to manipulate memory directly - which is risky though sometimes useful - C is one of the best languages in which to do it. Memory addresses are numbers, and C will let you work with those numbers in whatever way you want: add, subtract, multiply, divide... and if you didn't shudder at the suggestion of dividing a pointer because there are very, very few reasons to do so then C is not the language for you!

If you don't want to manipulate memory directly, you probably shouldn't be using C; stick with a nice garbage-collected, type-safe, object-oriented, cross-platform language. If you do want to manipulate memory directly, but you want more guarantees on what you can do with pointers, try Rust.

Re:The Descent to C (2013) by bluejekyll on Friday September 03, 2021 @12:22PM (#28406209)
Just wanted to clarify that Rust allows for the same manipulation as C, it just all has to happen in the context of an unsafe code block. I think your comment might be taken to imply that Rust isn’t as capable as C in that regard.
Re:The Descent to C (2013) by pjmlp on Saturday September 04, 2021 @05:21PM (#28419358)
Plenty of languages allow for the same memory handling capabilities, including BASIC.
Re:The Descent to C (2013) by junon on Friday September 03, 2021 @01:25PM (#28406942)
Eh? Says who? Every C programmer I've ever met knows about this. It's basic C.
Re:The Descent to C (2013) by jart on Friday September 03, 2021 @05:50PM (#28409815)
Yeah you have to do something like this if you want to truly raise eyebrows.

    /\
    */ best c comment
    *\
    /
Re:The Descent to C (2013) by Zababa on Friday September 03, 2021 @06:32PM (#28410154)
One trick that I like is replacing { and } with <% and %>.
Re:The Descent to C (2013) by junon on Friday September 03, 2021 @06:56PM (#28410365)
Wow, a new C trick I didn't know about. What's the history here?

Also, gross.

Re:The Descent to C (2013) by turminal on Friday September 03, 2021 @08:42PM (#28411069)
On some ancient systems { and } don't exist. So an alternarive made of more common characters is provided. There is also a two-character combination for [ and ] and a three character combination for |, & and some other characters. The feature is called digraphs/trigraphs and is disabled on most modern compilers by default.
Re:The Descent to C (2013) by Zababa on Saturday September 04, 2021 @11:17AM (#28415853)
> The feature is called digraphs/trigraphs and is disabled on most modern compilers by default.

Digraphs and trigraphs are treated differently. <% and %> are fine on GGC and Clang, but ??< and ??> are disabled by default. Both need the -trigraphs option.

Re:The Descent to C (2013) by junon on Saturday September 04, 2021 @09:17AM (#28414824)
Ah okay I knew about that whole thing, I didn't think C had so many of them.
Re:The Descent to C (2013) by dahfizz on Friday September 03, 2021 @12:28PM (#28406292)
I learned of this in college. Most C programmers know how C arrays work.
Re:The Descent to C (2013) by colejohnson66 on Friday September 03, 2021 @11:48AM (#28405744)
This “trick” has been know at least as far back as 2008: https://stackoverflow.com/questions/381542/with-arrays-why-i...
Re:The Descent to C (2013) by tialaramex on Friday September 03, 2021 @12:28PM (#28406295)
It's actually spelled out in K&R in more technical language:

"The array subscripting operation is defined so that E1[E2] is identical to *(E1+E2). Therefore, despite its asymmetrical appearance, subscripting is a commutative operation."

(my emphasis)

Re:The Descent to C (2013) by lifthrasiir on Friday September 03, 2021 @12:33PM (#28406369)
One of the very first IOCCC winners used the trick in 1984 (1984/anonymous):

    int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
    o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
Re:The Descent to C (2013) by jfrunyon on Friday September 03, 2021 @06:50PM (#28410320)
I think this is equivalent to:

    int i;
    int main(){
        for(
            ;
            i["]<i;++i){--i;}"]; // loop until i == 14? (the NUL byte on the end)
            read('-'-'-',i+++"hello, world!\n",'/'/'/') // read(0, <one byte of "hello, world!\n" at a time>, 1)
        ) {};
    }

    int read(j,i,p){
         write(j/p+p,i---j,i/i); // write(0/1+1, i-- - 0, 1) --> write(1, i, 1) --> write a byte to STDOUT
    }
Re:The Descent to C (2013) by jakeva on Friday September 03, 2021 @12:53PM (#28406598)
what does this program do? i compiled it and ran it and got no output. i hope i haven't fork bombed myself or something
Re:The Descent to C (2013) by lifthrasiir on Friday September 03, 2021 @01:05PM (#28406746)
Prints "hello, world!", assuming sizeof(int) == sizeof(char*) (and the same alignments and ABI, etc).