Live data from Hacker News

Summary of C/C++ integer rules

nayuki.io

31–40 of 98 posts

Re: Summary of C/C++ integer rules

#31
> Python only has one integer type, which is a signed bigint. Compared to C/C++, this renders moot all discussions about bit widths, signedness, and conversions – one type rules all the code. But the price to pay includes slow execution and inconsistent memory usage.

Well, the beauty of C is that you can have that too, if you wish, and you have many options to choose from.

Re: Summary of C/C++ integer rules

#32

In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…

> Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)?

For char, not sure, but the problem with signed overflow is not that you can't be sure whether it's 2's complement, it's that the compiler is allowed to assume it won't happen. So, if you read two numbers into 2 ints and add them up, then check for overflow somehow, the compiler will just remove your check while optimizing, since integrr addition can't overflow in a valid program.

Re: Summary of C/C++ integer rules

#33

In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…

DSP's have often uncommon sizes. tms320c5502 for example has following sizes: char-- 16 bits short --16 bits int --16 bits long-- 32 bits long long -- 40 bits float-- 32 bits double -- 64 bits

Indeed. The C28x line by the same company shares CHAR_BIT == 16 with C55. C28x is quite popular in power electronics applications.

"Relevant" is in the eyes of the beholder, and its all too easy to no-true-scotsman your way out of existing architectures. I claim that both of these architectures are relevant by virtue of suppliers continuing to make new chips that use them, and system builders continuing to select those chips in new products.

Re: Summary of C/C++ integer rules

#34

[Dons language lawyer hat] > floating-point number types will not be discussed at all, because that mostly deals with how to analyze and handle approximation errors that stem from rounding. By contrast, integer math is a foundation of programming and computer science, and all calculations are always exact in theory (ignoring implementations issues like overflow). Integer overflow is no mere implementation issue, any…

> char, signed char, and unsigned char are distinct types, but that's only true of char. That's correct, I was going to bring that up too. This is particularly important because char and unsigned char are special in that they are an exception the aliasing rules. That is, in this function: float foo(char* cp, float* fp) { *fp = 7; return *(float*)cp; } /* ... */ float f = 2; float g = foo((char*)&f, &f); Then g should…

>So you could end up with (at least) 5 types that are 8-bit wide!

Don't forget std::byte.

Re: Summary of C/C++ integer rules

#35

In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…

I heard that one case where defining int-overflow as wrapping would be very bad for performance is pointer arithmetic - e.g. offset a pointer by i times sizeof (type)). I think the x64 instruction "lea" accomplishes this. If this instruction is used, it is impossible to simulate 32-bit 2's complement overflow by just discarding the upper 32 bits of a 64-bit integer. So the UB that is associated with overflowing an in…

The part about lea doesn't seem especially convincing, it's not hard to imagine that pointer arithmetic could be defined such that overflow is still UB, while allowing regular signed integer arithmetic to overflow safely.

Re: Summary of C/C++ integer rules

#36

Earlier quoted context omitted.

I heard that one case where defining int-overflow as wrapping would be very bad for performance is pointer arithmetic - e.g. offset a pointer by i times sizeof (type)). I think the x64 instruction "lea" accomplishes this. If this instruction is used, it is impossible to simulate 32-bit 2's complement overflow by just discarding the upper 32 bits of a 64-bit integer. So the UB that is associated with overflowing an in…

The part about lea doesn't seem especially convincing, it's not hard to imagine that pointer arithmetic could be defined such that overflow is still UB, while allowing regular signed integer arithmetic to overflow safely.

I can't say much about this. What I know is that in C, pointer arithmetic is defined in terms of "normal" arithmetic. p[i] is defined as *(p + i). And (p + i) means to offset p by (i * sizeof *p), and that multiplication is computed as the type of i (e.g. (32-bit) int or even smaller type)

Re: Summary of C/C++ integer rules

#38

Earlier quoted context omitted.

Remember to add: that can actually run standard C++ (i.e. with exceptions)? Certainly you can find an architecture which may run some type of C-like language with strange arithmetic rules (e.g. DSPs). I would bet it's harder to find one such architecture where one can run standard C, and impossible to find one which can run standard C++.

This. I don't understand why everyone must suffer the pain of the possibility of weird char widths instead of just settling on using a non-standard C in a bunch of DSPs. It's not like you're going to link a bunch of regular run of the mill C libraries on them anyway.

[deleted]

Re: Summary of C/C++ integer rules

#39

In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…

I heard that one case where defining int-overflow as wrapping would be very bad for performance is pointer arithmetic - e.g. offset a pointer by i times sizeof (type)). I think the x64 instruction "lea" accomplishes this. If this instruction is used, it is impossible to simulate 32-bit 2's complement overflow by just discarding the upper 32 bits of a 64-bit integer. So the UB that is associated with overflowing an in…

I think the nasty cases are in supporting subregister-sized arithmetic. ARMv8 can perform almost any integer operation on its registers either as 64-bit or 32-bit registers.

The classic RISC machines could only perform full-register arithmetic. RISC-V has a small handful of instructions that can accelerate signed subregister arithmetic, but none that accelerate unsigned subregister arithmetic. So, if you need a 32-bit unsigned integer operation to guarantee wrap-around behavior on 64-bit RISC-V, the compiler may have to insert additional zero-extension instruction sequences if it cannot prove the absence of overflow.

Re: Summary of C/C++ integer rules

#40

In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…

This is the trap with 'undefined behaviour': it has nothing to do with portability, but it is a language level definition.

I.e., if the C std says it's 'undefined', it is not to be avoided for portability reasons (hardware, assembler), but it must not be used, end of story. The portability stuff is called 'implementation defined' in C, not 'undefined behaviour'. The problem is that the compiler can (and will!) exploit undefined behaviour rules. E.g., the following code is officially broken (and not just on weird hardware, but everywhere, as defined by the C std):

  int saturated_increment(int i)
  {
      if ((i + 1) 
The compiler may (and many will) remove the whole if() block, because i+1As one can imagine, when compilers started exploiting this, a lot of discussion about sensibility followed. And gcc added -fwrapv among other things.

(And the code would be fine if 'unsigned' was used in stead of 'int', because this is only a problem of signed ints.)

Post reply on HN