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!
Everything I wish I knew when learning C
391–400 of 401 posts
Re: Everything I wish I knew when learning C
#392Earlier 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.
Re: Everything I wish I knew when learning C
#393Earlier quoted context omitted.
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.
I can't think of any reason why get(a, i, j) is more readable than a[i][j].
Re: Everything I wish I knew when learning C
#394Earlier quoted context omitted.
Perhaps I am missing something in the spec - but trying this in various compilers, it seems that you *can* assign structs holding arrays to one another, but you *cannot* assign arrays themselves. This compiles: struct BigStruct { int my_array[4]; }; int main() { struct BigStruct a; struct BigStruct b; b = a; } But this does not: int main() { int a[4]; int b[4]; b = a; } That seems like an arbitrary restriction to me.
Essentially ‘b = a’ in the second example is equivalent to ‘b = &a[0]’ or assigning an array to a pointer. This is because if you use an array in an expression, it’s value is (most of the time) a pointer to the array’s first element. But the left element is not an expression, therefore it is referring to b the array. Example one works because no arrays are referred to in the expression side, so this shorthand so to s…
Re: Everything I wish I knew when learning C
#395Earlier quoted context omitted.
People like fast code.
In 2022, is there any other reasons to use C besides "fast code" or "codebase already written in C"?
So really the only time to use C is when the codebase already has it and there is a policy to stick to it even for new code, or when targeting a platform that simply doesn't have a C++ toolchain for it, which is unfortunately not uncommon in embedded.
Re: Everything I wish I knew when learning C
#396When 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…
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…
char str[256]; str = "asdf"
both str and "asdf" are not pointer-type expressions; they're both arrays (which is exposed by sizeof). The reason why this doesn't work is because C refuses to treat arrays as first-class value types - which is not an obvious thing to do regardless of how well you understand pointers or not. Other languages with arrays and pointers generally haven't made this mistake.Re: Everything I wish I knew when learning C
#397Earlier quoted context omitted.
Well there’s a little bit more to it. There is a type involved, and then there’s pointer arithmetic.
Well yes, but those aren't hard. Pointer arithmetic is merely knowing that any addition/subtraction done to a pointer is multiplied by the size of the type being pointed to. So if you're pointing to a 64-byte struct, then "ptr++;" adds 64 to the pointer.
Re: Everything I wish I knew when learning C
#398Earlier quoted context omitted.
... which is why I never understood why this is the convention rather than int* x, y. Does somebody know?
Spaces are ignored (except to separate things where other syntactical things like * or , aren't present), and * binds to the variable on the right, not the type on the left. I actually got this wrong in an online test, but I screenshotted every question so I could go over them later (! I admit, a dirty trick but I learned things like this from it, though I still did well enough on the test to get the interview). int*…
int* x, y;
declares two pointers.I think the syntax and the underpinning "declaration follows use" rule are what they got when they tried to generalize the traditional array declaration syntax with square brackets after the array name which they inherited directly from B, and ultimately all the way from Algol:
int x, y[10], z[20];
In B, though, arrays were not a type; when you wrote this: auto x, y[10], z[20];
x, y, and z all have the same type (word); the [] is basically just alloca(). This all works because the type of element in any array is also the same (word), so you don't need to distinguish different arrays for the purposes of correctly implementing [].But in C, the compiler has to know the type of the array element, since it can vary. Which means that it has to be reflected in the type of the array, somehow. Which means that arrays are now a type, and thus [] is part of the type declaration.
And if you want to keep the old syntax for array declarations, then you get this situation where the type is separated by the array name in the middle. If you then try to formalize this somehow, the "declaration follows use" rule feels like the simplest way to explain it, and applying it to pointers as well makes sense from a consistency perspective.
Re: Everything I wish I knew when learning C
#399Earlier quoted context omitted.
I agree with the factual things that you said (e.g. "entire program execution was meaningless"). Some stuff was hyperbolic ("time-travel back to the start of the universe, delete it"). > [compilers] will make transformations to the program whose effects could manifest before the UB-having code executes [...] It's monumentally rude to us poor programmers who have bugs in our programs. The first statement is factually…
> Integer division is a slow operation, and under the rules of C, it has no side effects. Then C isn't following this rule - crashing is a pretty major side effect.
Re: Everything I wish I knew when learning C
#400Earlier quoted context omitted.
> it is false in the general case, since division by zero has a side effect in the form of invoking undefined behaviour. They were careful to say “under the rules of C,” the rules define the behaviour of C. On the other hand, undefined behaviour is outside the rules, so I think they’re correct in what they’re saying. The problem for me is that the compiler is not obliged to check that the code is following the rules.…
> They were careful to say "under the rules of C," Yes, and under the rules of C , division by zero has a side effect, namely invoking undefined behaviour. > The problem for me is that the compiler is not obliged to check that the code is following the rules. That part's actually fine (annoying, but ultimately a reasonable consequence of the "rules the compiler can check" issue); the real(ly bad and insidious) proble…