Earlier quoted context omitted.
It's not just a memorization trick; that's exactly what the statement means. If you do int *x, y; You're saying that both *x and y are integers.
... which is why I never understood why this is the convention rather than int* x, y. Does somebody know?
Everything I wish I knew when learning C
31–40 of 401 posts
Re: Everything I wish I knew when learning C
#32This looks decent, but I'm (highly) opposed to recommending `strncpy()` as a fix for `strcpy()` lacking bounds-checking. That's not what it's for, it's weird and should be considered as obosolete as `gets()` in my opinion. If available, it's much better to do the `snprintf()` way as I mentioned in a comment last week, i.e. replace `strcpy(dest, src)` with `snprintf(dst, sizeof dst, "%s", src)` and always remember tha…
strncpy does have its odd and rare use-case, but 100% agree that it is not at all a “fix” for strcpy, it’s not designed for that purpose, and unsuited to it, being both unsafe (does not guarantee NUL-termination) and unnecessary costly (fills the destination with NULs). The strn* category was generally designed for fixed-size NUL-padded content (though not all of them because why be coherent?), the entire item is inc…
Re: Everything I wish I knew when learning C
#33Not crazy about this array explanation. Better wording would be: "I get a memory address that points to the first byte of a chunk of memory that is large enough to hold 5 ints and tagged as int"
> Essential compiler flags
Nitpick, but this is only true if you are on a gcc/clang platform.
> If you want to “return” memory from a function, you don’t have to use malloc/allocated storage; you can pass a pointer to a local data
It should be specified the memory must be passed by the caller for this to work. You can't create a var in a called function and return that (you can but you will get undefined behavior as that memory is up for grabs after the function returns).
> Integers are very cursed in C. Writing correct code takes some care.
Cursed how? No explanation.
Overall this article is not very good. I would add these to the lists:
General resources: Read the K&R book. Read the C spec. Be familiar with the computer architectures you are working on.
Good projects to learn from: Plan 9. Seriously. It's an entire OS that was designed to be as simple as possible by the same people who made Unix and the C.
Re: Everything I wish I knew when learning C
#34This looks decent, but I'm (highly) opposed to recommending `strncpy()` as a fix for `strcpy()` lacking bounds-checking. That's not what it's for, it's weird and should be considered as obosolete as `gets()` in my opinion. If available, it's much better to do the `snprintf()` way as I mentioned in a comment last week, i.e. replace `strcpy(dest, src)` with `snprintf(dst, sizeof dst, "%s", src)` and always remember tha…
strncpy does have its odd and rare use-case, but 100% agree that it is not at all a “fix” for strcpy, it’s not designed for that purpose, and unsuited to it, being both unsafe (does not guarantee NUL-termination) and unnecessary costly (fills the destination with NULs). The strn* category was generally designed for fixed-size NUL-padded content (though not all of them because why be coherent?), the entire item is inc…
Re: Everything I wish I knew when learning C
#35Some constructive feedback: > Here are the absolute essential flags you may need. I highly recommend including `-fsanitize=address,undefined` in there (docs: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.h... ). (Edit: But probably not in release builds, as @rmind points out.) > The closest thing to a convention I know of is that some people name types like my_type_t since many standard C types are like…
I find it difficult to imagine what that would even mean.
Re: Everything I wish I knew when learning C
#36These weren't mentioned in the post but have been very helpful in my journey as a C beginner so far:
- Effective C by Robert C. Seacord. It covers a lot of the footguns and gotchas without assuming too much systems or comp-sci background knowledge. https://nostarch.com/Effective_C (Also, how can you not buy a book on C with Cthulhu on the cover written by a guy with _three_ “C”s in his name?)
- Tiny C Projects by Dan Gookin, for a “learn by doing” approach. https://www.manning.com/books/tiny-c-projects
- Exercism's C language track: https://exercism.org/tracks/c
- Computer Systems, A Programmer's Perspective by Randal E. Bryant and David R. O'Hallaron for a deeper dive into memory, caches, networking, concurrency and more using C, with plenty of practice problems: https://csapp.cs.cmu.edu/
Re: Everything I wish I knew when learning C
#37Earlier quoted context omitted.
It's not just a memorization trick; that's exactly what the statement means. If you do int *x, y; You're saying that both *x and y are integers.
... which is why I never understood why this is the convention rather than int* x, y. Does somebody know?
I prefer to use the variant you described though, because it feels more natural to associate the pointer with the type itself. As far as I know, the only pitfall is in the multiple declaration thing so I just don't use it.
IMO, it's also more readable in this case:
int *get_int(void);
int* get_int(void);
The second one more clearly shows that it returns a pointer-to-int.Re: Everything I wish I knew when learning C
#38Some constructive feedback: > Here are the absolute essential flags you may need. I highly recommend including `-fsanitize=address,undefined` in there (docs: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.h... ). (Edit: But probably not in release builds, as @rmind points out.) > The closest thing to a convention I know of is that some people name types like my_type_t since many standard C types are like…
>That shouldn't be recommended, because names ending with "_t" are reserved.
Also C spec naming new things:
>_Atomic _Bool
I'm glad to see the C folks have a sense of humor.
Re: Everything I wish I knew when learning C
#39Re: Everything I wish I knew when learning C
#40typedef/enum/(_Generic)/etc should go (fix/cleanup function pointer type declaration). Only sized primitive types (u32/s32,u64/s64,f32/f64 or udw/sdw,uqw/sqw,fdw/fqw...). We would have only 1 loop statement "loop{}", no switch. I am still thinking about "anonymous" code blocks for linear-code variable sub-scoping (should be small compile-unit local function I guess). No integer promotion, no implicit cast (except for void* and maybe for literals like rust) with explicit compile-time/runtime casts (not with that horrible c++ syntax). Explicit compile-time/"scoped" runtime constants: currently it is only "scoped" runtime, with on some optimization passes to detect if the constant would be compile time. extern properly enforced for function plz (aka write proper headers with proper switches), and maybe "local" instead of "static" for compile-unit-only functions since all functions in a compile-unit are "static" anyway like global variables.
"Non-standard": ban attributes like binary format visibility (let the linker handle the fine details), packed (if your struct is packed and not compatible with the C struct, it should be byte defined, with proper pointer casts), etc.
Fix the preprocessor variable argument macro for good (now it is a mess because of gcc way and c++ ISO way, I guess we will stick to gcc way).
With the preprocessor and some rigorous coding, we should be able to approximate that with a "classic" C compiler, since we mostly remove stuff. Was told that many "classic" C compiler could output optional warnings about things like implicit casts and integer promotions.
In theory, this should help writting a naive "C-" compiler much more easily than a "classic" C compiler and foster real life alternatives.
I am sure stuff I said are plain broken as I did not write a C compiler.
I wonder how far rust is from this "C-" as it is expected to have a much less rich and complex, but more constraint, syntax than C.