4 ms·
How is this safer than enabling all warnings in GCC or clang? 'Type-safe' in this context does not mean that you get more compile errors, but that the format
by AlexanderDhoore 5y ago
How is this safer than enabling all warnings in GCC or clang?
'Type-safe' in this context does not mean that you get more compile errors, but that the format specifier does not need to specify the argument type, but just defines the print format. In fact, format strings with this library will have less compile-time checking (namely none) than with modern compilers for standard printf. This approach is still safer.
EDIT The answer is at the bottom apparently. Maybe put that up higher?
- edflsafoiewq 5y ago> There is absolutely no chance to give a wrong format specifier and access the stack (like printf does via stdarg.h) in undefined ways. This is particularly true for multi-arch development where with printf you need to be careful about length specifiers, and you might not get a warning on your machine, but the next person will and it will crash there. I usually need to compile for a few times on multiple architectures to get the integer length correct, e.g., %u vs %lu vs. %llu vs. %zu.
- kevin_thibedeau 5y agoThis is really annoying on architectures like ARM32 where size_t is closely related to unsigned int but uint32_t is long unsigned int and gets flagged as a different type. It becomes a real problem when using a stripped down printf like the one in newlib that doesn't support %zu.
- tinkersleep 5y agoExactly! Or on Windows 64-bit, where 'long' is 32-bit and 'size_t' is 'unsigned long long'.
- GeorgeTirebiter 5y agoThe Real Problem (tm) is: specifiers like 'char' and 'int' etc should not be allowed; they 'should be' things like c8 or i16 or u64 --- that is, specify the #of bits for that dataype in the type specifier. This is what sys/stdint.h is trying to fix. What maybe 'should' happen in C2x is: 'int' is defined as i16, 'long' as i32, 'long long' as i64 etc and then see which programs break. Because it's perfectly OK to have 16-bit 'ints' on a 64-bit arch. (size_t is what you use to deal with architecture-specific chunks). And then remove all this 'int' etc crap from C. (Obv, some 'compat switch' would need to exist, but you get the idea.)
- kevin_thibedeau 5y agoNo that should not happen. Integer types that adapt to the platform word size enhance portability. Nobody wants a 32-bit default int on an 8-bit platform and using uint8_t or uint16_t can introduce performance regressions on wider platforms. The traditional integer types are perfectly suited for scenarios where the exact width doesn't matter and you know the guaranteed minimum is good enough.
- arka2147483647 5y agoI would argue that most code nowdays iplicitly assumes that int is 32bit’s long, and wont work correctly in a 8bit platform anyways. If ’platform size conforming’ ints are used, they probably should be opt-in, instead of opt-out.
- kevin_thibedeau 5y agoThat's great for people weaned on Java's false promise of a uniform type system. Then you find out you want the behavior of unsigned integer overflow and have to jump through contortions to get it. You can't set a single standard for the default that works universally.
- dmitrygr 5y agoTo address the problem you mention, uint_fast8_t and co exist. It is at least 8 bits big, but whatever type is fastest that fits that requirement. So on an 8-bit system it is a uint8_t. on a 32-bit ARM is is a uint32_t. there is also uint_fast16_t and so on...
- GeorgeTirebiter 5y agoAs the programmer, I don't really care what the h/w does; if I specify u8 and every operation produces results 'as if' the type were 8 actual unsigned bits, eg, when using an underlying u32 type -- great. From 'my model' -- it's still a u8. But there must be no conceptual 'leaking' (behaviors that I experience using e.g. uint_fast8_t that are in any way different from behaviors I experience when using u8 ). I don't especially care how the HW works; because my 'virtual machine' is C. (yes, yes, I know Reality intrudes, and sometimes you need to get closer to the machine. But, isn't this because of 'leaking' between 'virtual machine' and 'actual machine' that I mention above?)
- kevin_thibedeau 5y agoFor Windows the reason they couldn't switch to LP64 is because they screwed up the type system with LONG and allowed it to be incorporated into OS structs. That prevents long from being 64-bit for the sake of rationality.
- thebruce87m 5y agoCan’t you just use the inttypes.h along with stdint fixed width types to avoid the multiple compiles? This stackoverflow answer gives an example: https://stackoverflow.com/questions/7597025/difference-between-stdint-h-and-inttypes-h https://stackoverflow.com/questions/7597025/difference-betwe...
- edflsafoiewq 5y agoOf course if you just do everything correctly you don't need safety. But if you are fallible it is nice to have.
- tinkersleep 5y agoOk, thanks for the hint. I put the most important infos into the intro: you just don't need 'll', 'l', 'z' modifiers for specifying sizeof(operand), as the compiler does that via _Generic.
- eps 5y agoAlso put an example in the first pageful. I almost lost hope while scrolling through the wall of format spec when I finally saw the first example.
- tinkersleep 5y agoOK, yes, good idea.