Live data from Hacker News

Everything I wish I knew when learning C

tmewett.com

351–360 of 401 posts

Re: Everything I wish I knew when learning C

#351

I like it, but the array details are a little bit off. An actual array does have a known size, that's why when given a real array `sizeof` can give the size of the array itself rather than the size of a pointer. There's no particular reason why C doesn't allow you to assign one array to another of the same length, it's largely just an arbitrary restriction. As you noted, it already has to be able to do this when assi…

Another one corner of the language where arrays actually being arrays is important is multidimensional array access:

    int arr[5][7];
    arr[3][5] = 4; // equivalent to *(*(arr + 3) + 5) = 4;
This works because (arr + 3) has type "pointer to int[7]", not "pointer to int". The resulting address computation is

    (char*)arr + 3 * sizeof(int[7]) + 5 * sizeof(int) ==
    (char*)arr + 26 * sizeof(int)
That's also another reason why types like "int [5][7][]" are legal but "int [5][][]" are not.

Re: Everything I wish I knew when learning C

#352
post #332

Earlier quoted context omitted.

That would be a nice little "gcc addition" to the C standard, honestly. To bad they spend most their time doing whatever it is they do.

I have long been convinced that WG14 has no real interest in improving C's security beyond what a Macro Assembler already offers out of the box. Even the few "security" attempts that they have made, still require separate pointer and length arguments, thus voiding any kind of "security" that the functions might try to achieve. However even a Macro Assembler is safer than modern C compilers, as they don't remove your…

One of the members of WG14 posted here a few days ago that they only use C89.

Re: Everything I wish I knew when learning C

#353

Earlier quoted context omitted.

IIRC this is valid in C99: void foo(size_t n) { int arr[n]; … }

How do you think it works? Does the compiler generate some kind of stack alloc? Stupid question: Does that mean a huge value for 'n' can cause stack overflow at runtime? I recall that threads normally get a fixed size stack size, e.g., 1MB.

It just moves the stack pointer by n which is O(1). It doesn’t initialize it of course. But my point is that the array size isn’t known at compile time.

Re: Everything I wish I knew when learning C

#354
Never use -Og for debug builds. It doesn't work. Use -O0.

If you try to debug a -Og built program you will not be able to print locals because the optimizer has removed them. People blame their debugger.

It's my humble opinion that -Og should be an alias for -O0. Broken for decades it's time to stop pretending it works.

Re: Everything I wish I knew when learning C

#355

I like it, but the array details are a little bit off. An actual array does have a known size, that's why when given a real array `sizeof` can give the size of the array itself rather than the size of a pointer. There's no particular reason why C doesn't allow you to assign one array to another of the same length, it's largely just an arbitrary restriction. As you noted, it already has to be able to do this when assi…

Another one corner of the language where arrays actually being arrays is important is multidimensional array access: int arr[5][7]; arr[3][5] = 4; // equivalent to *(*(arr + 3) + 5) = 4; This works because (arr + 3) has type "pointer to int[7]", not "pointer to int". The resulting address computation is (char*)arr + 3 * sizeof(int[7]) + 5 * sizeof(int) == (char*)arr + 26 * sizeof(int) That's also another reason why t…

Really, are multidimensional arrays an important part of the language?

The above code looks like it's indexing into an array of pointers. If you want a flat array, make a few inlined helper functions that do the multiplying and adding. Your code will be much cleaner and easier to understand.

Re: Everything I wish I knew when learning C

#356
post #332

Earlier quoted context omitted.

I have long been convinced that WG14 has no real interest in improving C's security beyond what a Macro Assembler already offers out of the box. Even the few "security" attempts that they have made, still require separate pointer and length arguments, thus voiding any kind of "security" that the functions might try to achieve. However even a Macro Assembler is safer than modern C compilers, as they don't remove your…

One of the members of WG14 posted here a few days ago that they only use C89.

Mind blown.

Re: Everything I wish I knew when learning C

#357
post #124

Earlier quoted context omitted.

This technique is used in Berkley sockets: the `sockaddr` type ( https://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys... ) is the "base" type for other types such as `sockaddr_ip` (for IPv4). But it's undefined behaviour according to ISO C due to the "strict aliasing" rule: https://en.cppreference.com/w/c/language/object#Strict_alias...

Strict aliasing allows you to convert between a pointer to a struct and a pointer to its first member, since two objects exist at that address, one with the type of the struct and one with the type of the first member. > A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed paddin…

Yes, that's the workaround described by @spacedcowboy and @leni53. I should have clarified that my comment on undefined behaviour was specifically for the case of two structs that start the same (e.g. "int x; int y;") as opposed to composition.

Re: Everything I wish I knew when learning C

#358

Earlier quoted context omitted.

Pointers are by far the most insidious thing about C. The problem is that nobody who groks pointers can understand why they had trouble understanding them in the first place. Once you understand, it seems so obvious that you cannot imagine not understanding what a pointer is, but at the beginning, trying to figure out why the compiler won't let you assign a pointer to an array, like `char str[256]; str = "asdf"`, is…

From my memory, the syntax of pointers really tripped me up. E.g., the difference between * and & in declaration vs dereferencing. I think this is especially confusing for beginners when you add array declarations to the mix.

Agreed. Complex declarations (e.g., array of pointers to functions) are non-intuitive:

http://www.ericgiguere.com/articles/reading-c-declarations.h...

https://cdecl.org/

I learned this from the book Expert C Programming by Peter van der Linden.

Re: Everything I wish I knew when learning C

#359
post #84
post #59

Earlier quoted context omitted.

But wouldn't one be required to include a particular header in such case (i.e. the correct header for defining a particular type)? I mean, no typedef names are defined in the global scope without including any headers right? Like I find it really weird that a type ending in _t would be UB if there is no such typedef name declared at all. Or is this UB stuff merely a way for the ISO C committee to enforce this without…

[Note: What I originally wrote in my top-level comment was inaccurate; I edited that comment, but later posted another update: https://news.ycombinator.com/item?id=33773043#33775630 .] The purpose of this particular naming rule is to allow adding new typedefs such as int128_t. The "undefined behaviour" part is for declaration of any reserved identifier (not specifically for this naming rule). I don't know why the sta…

[Edit: My link to the behaviour classes was wrong (it was for C++ instead of C), it should have been https://en.cppreference.com/w/c/language/behavior]

Re: Everything I wish I knew when learning C

#360
post #93

Earlier quoted context omitted.

From https://www.open-std.org/JTC1/sc22/wg14/www/docs/n2625.pdf : > The goal of the future language and library reservations is to alert C programmers of the potential for future standards to use a given identifier as a keyword, macro, or entity with external linkage so that WG14 can add features with less fear of conflict with identifiers in user’s code. However, the mechanism by which this is accomplished is overly…

So... instead of mandating implementations to warn about (re)defining a reserved identifier, they introduce another class of "not yet reserved indentifiers" and advise implementations to warn about defining such identifiers in the user code — even though it's completely legal, — until the moment the implementation itself actually uses/defines such an identifier at which point warning about such redefinition in the us…

> Besides, there is already a huge swath of reserved identifiers in C, why do they feel the need to make an even larger chunk of names unavailable to the programmers?

The C23 change was mostly to downgrade some of the existing reserved identifiers from "reserved" to "potentially reserved". (It also added some new reserved and potentially reserved identifiers, but they seem reasonable to me.)

Post reply on HN