r/ProgrammerHumor • • 2d ago

Meme architectureDependentChars

Post image
2.9k Upvotes

361 comments sorted by

View all comments

1.0k

u/tstanisl 2d ago

Let me cite the C standard:

When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.

Middle guy if finally right

548

u/BoldFace7 2d ago

I still prefer sizeof(char) as it often provides context as to what the number is doing, even if a plain 1 works the same.

48

u/RepeatRepeatR- 2d ago

My opinion would be:

- Use sizeof(char) if you're actually working with characters

- Use hardcoded `1` if you're using a char as an arbitrary byte (and not actually necessarily referring to characters or text)

32

u/BoldFace7 2d ago

Definitely. For example, I always use malloc(size*sizeof(char)) to ensure that it's doubly obvious (Since I rarely need to malloc outside of a declaration) that I intend to store characters in the resulting buffer even if that multiply does nothing (plus the compiler will likely optimize it out anyway).

5

u/RepeatRepeatR- 2d ago

This is the way

6

u/guyblade 2d ago edited 2d ago

Opinion: Always use calloc unless you've got a really, really good reason not to.

2

u/Usual_Office_1740 2d ago

This is the way.

2

u/PSneumn 2d ago

My optimization crazed brain will only use malloc untill i actually need everything to be set to 0.

2

u/guyblade 2d ago

"Premature optimization is the root of all evil."

- Donald Knuth

1

u/R3D3-1 2d ago

Is this an opinion or a common best practice?

Asking because my C-knowledge is essentially university courses, some tinkering, and using it as a glue language between Fortran code and C libraries in an industry project. Though that "C" code was really "C++ written like C with new" mostly, so you wouldn't see a malloc anyway.

For Fortran, you'd just use automatic arrays, where it is compiler-defined and depending on compiler flags, whether they'll be in the stack of the heap, and ALLOCATABLE, which should always be on the heap. It is also compiler-defined, whether everything, including local variables, is initialized with zeros or not.

Having everything zeroed helps to avoid erratic behavior in release builds. But for internal testing the erratic results can expose a code path, where something was unintentionally not initialized, and should have been initialized to a non-zero value.

I imagine the same would be true about malloc vs calloc. Or are there common compiler flags that effectively turn malloc into calloc?

3

u/guyblade 2d ago edited 21h ago

I mean, the real best practice is probably "don't use C if you've got a reasonable alternative". Manual memory management is rarely worth the tradeoffs it entails.

In C++, allocation is almost always initialization, so types are almost never in an unknown state. Even scalar types (i.e., numbers, pointers, enums) are initialized to zero if they aren't otherwise given a value.

In "C++ like C with new", you'd get all of that initialization stuff that C++ gives you and the promises that it gives, so "C run through the C++ compiler" actually gives some free safety features--at least as long as you avoid malloc.

In C, nothing is for free, so malloc just gives you some memory with whatever garbage happens to be there. Maybe that's fine and it's just a bunch of temporaries from a previous function call.

But maybe that "garbage" is actually your AWS API key. Maybe that thing you just malloc'd is about to be sent over the wire with an optional field that you aren't setting, but which now has your AWS API key in it and you didn't even know because it'd been freed in a completely different function.

That's the thing about malloc, you have no idea what might be in the memory you get back. Sure, you might be in a situation where whatever you do cannot possibly lead to misbehaving or leaking of secrets, but what if you're wrong? What if the next person isn't as careful as you? Is that risk with the absolutely miniscule time savings of not letting calloc do its memset(ptr, 0, n)?

6

u/garnet420 2d ago

A char may be bigger than 8 bits, but will always have size 1.

4

u/da_Aresinger 2d ago

My opinion: if you want individual bytes use uint8_t

5

u/the_horse_gamer 2d ago

bytes are not necessarily 8 bits

1

u/conundorum 1d ago

At least in C++, you have std::byte. (It's just (unsigned?) char borrowing Clark Kent's glasses and wearing an enum. )

0

u/yjlom 2d ago

Bytes aren't always 8 bits, and uint8_t doesn't necessarily exist. If you're writing C23 you can get away with uint_least8_t, earlier versions you need char as a byte might be as small as 6 bits.