Live data from Hacker News

Everything I wish I knew when learning C

tmewett.com

1–10 of 401 posts

Re: Everything I wish I knew when learning C

#3
Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition. In the following example, shouldn't there be an asterisk * before the data argument in the getData function call? The way I understand it the function is expecting a pointer so you would need to pass it a pointer of the data object.

> "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:

void getData(int *data) { data[0] = 1; data[1] = 4; data[2] = 9; }

void main() { int data[3]; getData(data); printf("%d\n", data[1]); } "

Re: Everything I wish I knew when learning C

#4

Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition. In the following example, shouldn't there be an asterisk * before the data argument in the getData function call? The way I understand it the function is expecting a pointer so you would need to pass it a pointer of the data object. > "If you want to “return” memory from a function, you don’t h…

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[0], which is an int. You don't want to pass an int, you want to pass an *int.

Re: Everything I wish I knew when learning C

#5

Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition. In the following example, shouldn't there be an asterisk * before the data argument in the getData function call? The way I understand it the function is expecting a pointer so you would need to pass it a pointer of the data object. > "If you want to “return” memory from a function, you don’t h…

the local variable data effectively decays to int*.

*data would give you an int, &data would give you an int*.

Re: Everything I wish I knew when learning C

#6
Some 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

Beware that names beginning with "int"/"uint" and ending with "_t" are reserved in .

[Edited; I originally missed the part about "beginning with int/uint", and wrote the following incorrectly comment: "That shouldn't be recommended, because names ending with "_t" are reserved. (As of C23 they are only "potentially reserved", which means they are only reserved if an implementation actually uses the name: https://en.cppreference.com/w/c/language/identifier. Previously, defining any typedef name ending with "_t" technically invokes undefined behaviour.)"]

The post never mentions undefined behaviour, which I think is a big omission (especially for programmers coming from languages with array index checking).

> void main() {

As @vmilner mentioned, this is non-standard (reference: https://en.cppreference.com/w/c/language/main_function). The correct declaration is either `int main(void)` or the argc+argv version.

(I must confess that I am guilty of using `int main()`, which is valid in C++ but technically not in C: https://stackoverflow.com/questions/29190986/is-int-main-wit...).

> You can cast T to const T, but not vice versa.

This is inaccurate. You can implicitly convert T* to const T*, but you need to use an explicit cast to convert from const T* to T*.

Re: Everything I wish I knew when learning C

#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 that "%s" part. Never put src there, of course.

There's also `strlcpy()` on some systems, but it's not standard.

Re: Everything I wish I knew when learning C

#8
post #6

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

Certainly yes, but for debug builds and tests. It can be heavyweight for production.

Re: Everything I wish I knew when learning C

#9

Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition. In the following example, shouldn't there be an asterisk * before the data argument in the getData function call? The way I understand it the function is expecting a pointer so you would need to pass it a pointer of the data object. > "If you want to “return” memory from a function, you don’t h…

No, it's fine.

The name of an array decays to a pointer to the first element in various contexts. You could do `&data[0]` but it means exactly the same thing and would read as over-complicated things to C programmers.

Re: Everything I wish I knew when learning C

#10
post #8
post #6

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

Certainly yes, but for debug builds and tests. It can be heavyweight for production.

[deleted]
Post reply on HN