5 ms·
Almost all of these examples would be sloppy programming in real code. The “int”, “short”, “long”, “long long” and “char” types are generic labels which shouldn
by bluetomcat 4y ago
Almost all of these examples would be sloppy programming in real code. The “int”, “short”, “long”, “long long” and “char” types are generic labels which shouldn’t be used where size and signedness matters. For a guarantee of size and signedness one should use the “[u]intXX_t” types. For sizes and pointer arithmetic - size_t. For subtracting pointers - ptrdiff_t. You simply wouldn’t have most of these issues if you stick to the correct types.
- rwmj 4y agoAbsolutely. int is a "code smell" for us, except in some well-defined cases (storing file descriptors for example). If someone is using int to iterate a loop, then the code is more usually wrong than right, they should be using size_t.
- fizzynut 4y agoI don't think a for loop using an int is bad or even "more wrong than right". If anything int is much better than using size_t. Using an integer, in the 1000s of for loops I've written, none get even remotely close to the billions - it is optimizing for a 1 in a million case, and if I know something can run into the billions of iterations I'm going to pay more attention to anyway. I've seen 0 occurrences of bugs relating to this kind of overflow. Using a size_t, it is effectively an unsigned integer that risks underflowing which can easily cause bugs like infinite loops if decrementing or other bugs if doing any index arithmetic. I've seen many occurrences of these kind of bugs.
- rwmj 4y agoOn Linux/x86-64 int is 31 bits, so you've probably introduced "1000s" of security bugs where the attacker only needs the persistence to add 2 billion items to a network input, local file or similar, to generate a negative pointer of their choosing. Any such code submitted to one of our projects would be rejected or fixed to use the proper type.
- fizzynut 4y agoPlease don't make this adversarial. I've not introduced a security bug in every for loop I've written. What I've written shouldn't be controversial, just take a look at Googles style guide: "We use int very often, for integers we know are not going to be too big, e.g., loop counters. Use plain old int for such things. You should assume that an int is at least 32 bits, but don't assume that it has more than 32 bits. If you need a 64-bit integer type, use int64_t or uint64_t. For integers we know can be "big", use int64_t. You should not use the unsigned integer types such as uint32_t, unless there is a valid reason such as representing a bit pattern rather than a number, or you need defined overflow modulo 2^N. In particular, do not use unsigned types to say a number will never be negative. Instead, use assertions for this. If your code is a container that returns a size, be sure to use a type that will accommodate any possible usage of your container. When in doubt, use a larger type rather than a smaller type. Use care when converting integer types. Integer conversions and promotions can cause undefined behavior, leading to security bugs and other problems."
- mananaysiempre 4y agoUnfortunately, even if you’re using uint16_t (which, remember, the C standard does not guarantee exists) on a platform with (say) 32-bit integers, you’re still actually computing in signed int due to promotion.
- scatters 4y agoThe true types (int, unsigned etc) are correct for local variables, since they describe registers. The sized aliases are correct for struct fields and for arrays in memory. You should prefer signed types for computing (if not storing) sizes and for pointer arithmetic, since they are more forgiving with underflow.