Live data from Hacker News

Everything I wish I knew when learning C

tmewett.com

261–270 of 401 posts

Re: Everything I wish I knew when learning C

#261

The one thing missing from this list: Compiler optimizations can have undesirable effects. A trivial example I ran into in an older job: I was compiling a program that relied on libm.so (the standard math library you get when including math.h). Now I wanted the code to use my own custom libm.so - not the one that was installed in /usr/lib or wherever, so I ensured it was dynamically compiled. My code had some calls l…

C doesn't have namespaces so the compiler is certainly within its right to deduce that the sin() function is the one from the standard library.

Actually even in C++ after the compiler performs the unqualified name lookup if the result of the lookup is the standard sin() function it will make use of its internal knowledge about the function to do optimization.

Remember that the C or C++ standard doesn't deal with compilers and linkers; the standard deals with the "implementation" as a whole.

Re: Everything I wish I knew when learning C

#262

Earlier quoted context omitted.

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

Not thread local storage. Plain function statics are initialized on first use in c++ (if the initializer is not trivial), and this initialization is thread safe. There is a simple algorithm to implement it that has very little overhead on the already initialized case that is known as magic statics (it is basically an instance of the double checked locking pattern).

Re: Everything I wish I knew when learning C

#263
post #177

Earlier quoted context omitted.

> 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. IIRC C has an informal guarantee that no primitive syntax will ever cause the CPU to do more than O(1) work at runtime. Assignment is always O(1), and therefore assignment is limited to scalars. If you need assignment that might do O(N) work, you need to call a stdlib f…

> Assignment is always O(1) This depends on what you consider to be O(1) - being that the size of the array is fixed it's by definition O(1) to copy it, but I might get your point. I think in general your point isn't true though, C often supports integer types that are too large to be copied in a single instruction on the target CPU, instead it becomes a multi-instruction affair. If you consider that to still be O(1)…

I think the meaning here is that assignment is never O(N) for any variable N computed at runtime. Of course, you can create arbitrarily large assignments at compile time, but this always has an upper bound for a given program.

Re: Everything I wish I knew when learning C

#264
post #50

Earlier quoted context omitted.

No, it's correct. The asterisk is a little inconsistent, in that it means two opposite things. In the declaration it means "this is a pointer." However, in an expression , it means "this is the underlying type" and serves to dereference the pointer. int a = 5; int *x; // this is a pointer x = &a; int c = *x; // both c and *x are ints If it were *data, it would be equivalent to *(data + 0), which is equivalent to data…

Thanks. Now I understand why I found pointers difficult. It's the declaration that confused me.

I think it would help if beginners learn a language other than C to learn about pointers. My first language was Pascal, and it didn't have a confusing declaration syntax, nor did it have a confusing array decay behavior so it was much much easier to learn. Nowadays of course I don't think about it but those details mattered to beginners.

Re: Everything I wish I knew when learning C

#265
post #252

Earlier quoted context omitted.

And any structure is O(1), not O(n), because C structures are not parameterized.

memcpy is not O(1)

It's O(1) relative to any size computed at runtime: that is, running the same program (with the same array size) on different inputs will always take the same of work for a given assignment.

Re: Everything I wish I knew when learning C

#266

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…

I really wish that int arr[5] adopted the semantics of struct { int arr[5]; } -- that is, you can copy it, and you can pass it through a function without it decaying to a pointer. Right now in C: typedef uint32_t t1[5]; typedef struct { uint32_t arr[5]; } t2; void test(t1 a, t2 b) { t1 c; t2 d; printf("%d %d %d %d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d)); } will print 4, 20, 20, 20. I understand that array typ…

> I really wish that int arr[5] adopted the semantics of struct { int arr[5]; }

You and me both. In fact, D does this. `int arr[5]` can be passed as a value argument to a function, and returned as a value argument, just as if it was wrapped in a struct.

It's sad that C (and C++) take every opportunity to instantly decay the array to a pointer, which I've dubbed "C's Biggest Mistake":

https://www.digitalmars.com/articles/C-biggest-mistake.html

Re: Everything I wish I knew when learning C

#267

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 weird property about C arrays is that &arr == arr. The reference of an array is the pointer to the first element, which is what `arr` itself decays to. If arr was a pointer, &arr != arr.

Is today international speak like a pirate day? arr arr arr

Re: Everything I wish I knew when learning C

#268
post #122

I find this article very strange, perhaps because I started using 'c' so long ago. To the bullet points: (1) In general, 'c' is always 'c' at the command line, regardless of the platform. (2) yes, there are options and build tools, but cc my_program.c -o my_program works fine. I have a very hard time figuring out how to compile/run java. (3) hard to see how this has anything to do with 'C', vs any other compiled lang…

Now I need to make a C dialect with better string handling built-in and call it 'C'

Working on it so you don't have to !

You'll enjoy comfy stuff like

  let s = "string.."
  s += "handled"
The runtime Buffer type is already operational (https://github.com/alcover/buffet)

Re: Everything I wish I knew when learning C

#270
post #74

> Everything I wish I knew when learning C By far my biggest regret is that the learning materials I was exposed to (web pages, textbooks, lectures, professors, etc.) did not mention or emphasize how insidious undefined behavior is. Two of the worst C and C++ debugging experiences I had followed this template: Some coworker asked me why their function was crashing, I edit their function and it sometimes crashes or do…

I haven’t used C or C++ for anything, but in writing a Game Boy emulator I ran into exactly that kind of memory corruption pain. An opcode I implemented wrong causes memory to corrupt, which goes unnoticed for millions of cycles or sometimes forever depending on the game. Good luck debugging that! My lesson was: here’s a really really good case for careful unit testing.

Yeah for that kind of stuff you want tests on every single op checking they make exactly the change you expect.
Post reply on HN