7 ms·
All C's native datatypes should be avoided for cross-platform data structures (networking, databases, file storage) because the standard only guarantees minimum
by jagrsw 2y ago
All C's native datatypes should be avoided for cross-platform data structures (networking, databases, file storage) because the standard only guarantees minimum sizes. Additional problem is the endianess.
uint64_t is a bit verbose, many re-def this to u64.
- coldpie 2y agoI think I agree, but I'd be interested in more discussion about this. I always understood the native types to be the "probably most efficient" choice, for when you don't actually care about the width. For example, you'd choose int for a loop index variable which is unlikely to hit width constraints because it's the "probably most efficient" choice. If you're forced to choose a width, you might choose a width that is less efficient for the architecture. Is that understanding correct? Historically or currently? Either way, I think I now agree that unspecified widths are an anti-feature. There's value in having explicitly specified limits on loop index variables. When you write "for(int32_t i; ...)", it causes you to think a bit, "hey can this overflow?" And now your overflow analysis will be true for all arches, because you thought about the width that is actually in use (32-bits, in this case). It keeps program behavior consistent & easier to reason over, for all arches. That's my thinking, but I'd be interested to hear other perspectives.
- 2ndbigbang 2y agoThere is int_fast32_t and int_least32_t but it is probably less confusing to just use exact sized types (and would make porting to other architectures simpler).
- kibwen 2y ago> I always understood the native types to be the "probably most efficient" choice, for when you don't actually care about the width. This itself is a platform-specific property, and is thus non-portable (not in the sense that your code won't run, but in the sense that it might be worse for performance than just using a known small integer when you can).
- nyrikki 2y agoHistorically that is incorrect. Remember that the C standard came about many years after the language was already in use, the C abstract machine wasn't an explicitly design for portability and performance, it was documenting an existing system. C compilers being performant and portable is partly due to luck but mostly due to hard work by very smart people. Last time I looked, clangs analysis and optimizing code was more than a quarter of a million lines as an example. C being imperative is probably a lens for understanding how the type of optimization you are talking about are opportunistic and not intrinsic. Another lens is to consider that the PDP11 had flat memory, but NUMA, l2 and l3 caches and deep pipelines make the compiler far more complicated despite maintaining that simple model on the abstract machine. Ironically, FORTRAN, which was written on IBM machines that had decrementing index registers. While the base one indexing is explained as being simply a choice of lowest value. In the historic context is is better conceptualized as a limit index. That more closely matches what you are describing above. If you look at the most recent CPP versions adding ranges, that is closer to both FORTRAN and the above IMHO. https://en.cppreference.com/w/cpp/ranges https://en.cppreference.com/w/cpp/ranges That history is complicated because Dennis Ritchie's work on college was on what he called 'loop programming', what we would call the structured paradigm today. That does have the concept that any loop that you know the number of iterations will always halt, but being imperative, C doesn't really enforce that although any individual compiler may. C compilers are u reasonably effective in optimization, but that is in spite of the limits of the C abstract machine, not because of it . As shown above, all it takes is one powerful actor like MS making a decision, that probably was justified at the time, to introduce side effects across all platforms. Often it is safe to assume that the compiler will make good decisions, other times you have to force it to make the correct decision. But using the default types is a decision more of a choice to value portability than about performance IMHO.
- nyrikki 2y agoProbably should point out that for loops in C are syntactic sugar for while loops at the language level. for loop Executes a loop. Used as a shorter equivalent of while loop. https://en.cppreference.com/w/c/language/for https://en.cppreference.com/w/c/language/for I am amazed at how good compilers are today. There is also the difference between portability, where it means it compiles vs meaning that the precision and behavior is similar across platforms. long would be more portable for a successful compilation but may cause side effects. I shouldn't have switched meanings in the above reply context.
- marcosdumay 2y ago> I always understood the native types to be the "probably most efficient" choice Both of int32_t on Windows and int64_t on Unixes can't be the "probably most efficient" choice on the same machine. Besides, struct bloating is a perfectly fine C optimization that your compile can do at any time to get the most efficient implementation without that "probably" part. It almost never does, tough, because it's a shitty operation and because CPUs that handle 64 bits perfectly but fumble around with 32 bits are a historic oddity only.
- EasyMark 2y agoI so much wish stdint would have gone with the more sane u64 i64, u32, i32, etc I redefine them for my personal projects but stick to the standard on other projects.