15 comments

[ 3.3 ms ] story [ 46.0 ms ] thread
I'm not sure I get this article. I somewhat agree with the conclusion (it's ok to pass structures by value! sometimes!), but the (counter)example code looks like it's compiled with warnings off.
Useless article. This person has never heard of `const`, which is part of C89.
Perhaps they have, and just know how useless it is. Const doesn't prevent you from modifying values that were passed in, it just makes it undefined behaviour if you do. Most C programmers don't need any help with making their programs undefined behaviour.
If nothing else, const in an api is a very clear and welcome indication of what to expect.

Like myapi(uint8_t *dest, const uint8_t *src, size_t dest_len, size_t src_len), it's very clear what will be doing what with what.

You can cast const away and do something unexpected in there, but that's on you doing the Wrong Thing.

In C, you don't even have to cast const away, since all pointer types are implicitly convertible between each other. So you can pass a `const int*` to a function that takes a `int*` with only a compiler warning, no errors.
Actually what's a warning or not is implementation defined, it's not defined in C.

If you're serious about your code, you will turn on -Werror -Wall -Wextra and anything else you don't like the look of, use static analysis and so on that makes this class of complaint moot.

> If you're serious about your code, you will turn on -Werror -Wall -Wextra and anything else you don't like the look of, use static analysis and so on that makes this class of complaint moot.

No it doesn't. No-one has ever come up with a concrete set of rules for how to build C and not have embarrassingly basic security bugs. It's always some vague "oh, if you use enough warnings and static analysis it's not a problem", and if you have security bugs evidently you weren't using enough, and if it's impossible to write anything or use any libraries then evidently you were using too many. A C language that actually works is vaporware.

In that case I would have welcomed a simple sentence stating why they won't use 'const'. I very much feel they're not even aware of it. The general feeling I get is that they're trying to work without a compiler, notably without any optimization not warning - some of the code (passing short* instead of int*) will raise warnings -it's likely optimisations passes will often remove some of the copy overhead - the compiler will bark if you write to 'const'

So my general feeling is that they're trying to work assuming people will want to screw their API intentionally; which looks quite unreasonable to me. A bit context about the 'why' would be interesting

No competent embedded C programmer could write this article without explaining why "const" is not a useful defence against this imagined problem, much less avoid even using the term "const" once.
What's terrible about const in C is you'll end up casting non const pointers to const ones all over the place thus blowing holes in the already weak type system.
This article seems to make performance assertions that are not supported by what actually happens.

E.g. "Passing by value is slower, since a new variable has to be created. Passing by reference just passes an address and the code uses that address – no new variable is created." is not right for the example involving an int*, as passing a pointer is clearly as much data to copy as an int (and in the non-pointer case it will all end up in (faster) registers).

Similarly if you paste the "Returning a copy of a structure" example into godbolt you'll see GetDateTime4 writes directly into the caller's pointer. https://godbolt.org/z/Wj4Gn1YaP

Guy seems a bit new to C.

pointers-to-structs ARE pointers-to-objects. That's the default way to operate on objects in a huge amount of code.

Don't use strncpy(), if it hits the limit it doesn't end the copy with NUL, causing random crashes.

Quite a few people have concluded that generally, despite the standard library using them, NUL-terminated C string were not the Right Way and it's better to have a struct with the pointer and a size_t length (and perhaps a size_t representing the possibly larger allocated length). This eliminates NUL handling, and strlen() as well and since everything can cheaply know the length, can be the basis of more secure code.

Is there an alternate function which should be used instead of strncopy()?
There are various 'safer' versions of it, a common one is strlcpy() from bsd (which is in glibc etc)

https://linux.die.net/man/3/strlcpy

That's right, I knew this at some point but haven't been doing much C lately. Thank you for the refresh!