Live data from Hacker News

Everything I wish I knew when learning C

tmewett.com

211–220 of 401 posts

Re: Everything I wish I knew when learning C

#212

Earlier quoted context omitted.

Personally, I've found that some of the optimizations cause undefined behavior, which is so much worse. You can write perfectly good, strict C that does not cause undefined behavior, then one pass of optimization and another together can CAUSE undefined behavior. When I learned this, if it was and is correct, I felt that one could be betrayed by the compiler.

Any optimization that causes undefined behavior is bugged – please report them to your compiler's developers.

By definition an optimisation can’t cause UB as UB is a langage level construct.

An optimisation can cause a miscompilation. They happens and is very annoying.

Re: Everything I wish I knew when learning C

#213
post #7

This 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…

Would it be a sin to use memcpy() and leave things like input validation to a separate function? I'm nervous any time somebody takes a function with purpose X and uses it for purpose Y.

If you really need a fast strcpy then probably not, but in most situations snprintf will do the job just fine. And will prevent heartache.

Re: Everything I wish I knew when learning C

#214
post #203

Earlier quoted context omitted.

I'm not sure that's a productive way to think about UB. The "weirdness" happens because the compiler is deducing things from false premises. For example, 1. Null pointers must never be dereferenced. 2. This pointer is dereferenced. 3. Therefore, it is not null. 4. If a pointer is provably non-null, the result of `if(p)` is true. 5. Therefore, the conditional can be removed. There are definitely situations where many…

This is the problem; every compiler outcome is a series of small logic inferences that are each justifiable by language definition, the program's structure, and the target hardware. The nasal demons are emergent behavior. It'd be one thing if programs hitting UB just vanished in a puff of smoke without a trace, but they don't. They can keep on spazzing out literally forever and do I/O , spewing garbage to the outside…

> I personally find that offensive and rude that tools get away with being so garbage that they can't even promise to help you crash and diagnose your own problems.

This is literally why newer languages like Java, JavaScript, Python, Go, Rust, etc. exist. With the hindsight of C and C++, they were designed to drastically reduce the types of UB. They guarantee that a compile-time or run-time diagnostic is produced when something bad happens (e.g. NullPointerException). They don't include silly rules like "not ending a file with newline is UB". They overflow numbers in a consistent way (even if it's not a way you like, at least you can reliably reproduce a problem). They guarantee the consistent execution of statements like "i = i++ + i++". And for all the flak that JavaScript gets about its confusing weak type coercions, at least they are coded in the spec and must be implemented in one way. But all of these languages are not C/C++ and not compatible with them.

Re: Everything I wish I knew when learning C

#215
post #214
post #203

Earlier quoted context omitted.

This is the problem; every compiler outcome is a series of small logic inferences that are each justifiable by language definition, the program's structure, and the target hardware. The nasal demons are emergent behavior. It'd be one thing if programs hitting UB just vanished in a puff of smoke without a trace, but they don't. They can keep on spazzing out literally forever and do I/O , spewing garbage to the outside…

> I personally find that offensive and rude that tools get away with being so garbage that they can't even promise to help you crash and diagnose your own problems. This is literally why newer languages like Java, JavaScript, Python, Go, Rust, etc. exist. With the hindsight of C and C++, they were designed to drastically reduce the types of UB. They guarantee that a compile-time or run-time diagnostic is produced whe…

Yes, and my personal progression from C to C++ to Java and other languages led me to design Virgil so that it has no UB, has well-defined semantics, and yet crashes reliably on program logic bugs giving an exact stack traces, but unlike Java and JavaScript, compiles natively and has some systems features.

Having well-defined semantics means that the chain of logic steps taken by the compiler in optimizing the program never introduces new behaviors; optimization is not observable.

Re: Everything I wish I knew when learning C

#216
post #98

When I first learned C - which also was my first contact with programming at all - I did not understand how pointers work, and the book I was using was not helpful at all in this department. I only "got" pointers like three or four years later, fortunately programming was still a hobby at that point. Funnily when I felt confident enough to tell other people about this, several immediate started laughing and told me w…

My experience with pointers was the inverse of yours. My first programming language was Java, and I spent many hours puzzling out reference types (and how they differed from primitive types). I only managed to understand references after somebody explained them as memory addresses (e.g. the underlying pointer implementation). When I later learned C, I found pointers to be delightfully straightforward. Unlike references in Java, pointers are totally upfront about what they really are!

Re: Everything I wish I knew when learning C

#217

I was born in '74 so the last generation to start with C and go to other, higher-level, languages like Python or JavaScript. Going in this direction was natural. I was amazed by all the magic the higher-level languages offered. Going the other direction is a bit more difficult apparently. "What do you mean it does not do that?". Interesting perspective indeed!

Introductory programming courses at the University of Arizona were still taught in C when I was a freshman in 2008

Re: Everything I wish I knew when learning C

#219
My college taught us pascal and x86 asm before teaching us C. I think that was perfect because "bookending" it with a high-level language and a low-level one helped put C in perspective nicely. Knowing asm definitely helped to demystify pointers in C, which is usually a stumbling block for novice programmers.

Re: Everything I wish I knew when learning C

#220

Decent article. A couple minor points: c89 or c99, not c98. Plain static variables aren't thread-safe by default, true, but there's also _Thread_local

I haven't written actual C code in decades. Did C11 get magic statics with thread-safe initialization like C++11? Does C even have non-trivial initialization of statics local variables?

I don't know why it would be magic to have thread-local storage. Thread-local variables are either static or extern. Thread-local static variables are initialized like normal static variables (initialization on declaration line occurs on first instantiation), but with a separate copy per thread.

N1570, sec. 6.2.4, para. 4: An object whose identifier is declared with the storage-class specifier _Thread_local has thread storage duration. Its lifetime is the entire execution of the thread for which it is created, and its stored value is initialized when the thread is started. There is a distinct object per thread, and use of the declared name in an expression refers to the object associated with the thread evaluating the expression.

N1570, sec. 6.7.9, para. 10: If an object that has static or thread storage duration is not initialized explicitly, then [it is initialized to NULL or 0 as appropriate, including all-bits-zero padding in structs]

Post reply on HN