1

Have a look at the following piece of code:

#include <stdio.h>

int main(void)  
{  
int a;

a = 2147483647;
printf("a + 1 = %d \t sizeof (a + 1) = %lu\n", a + 1, sizeof (a + 1));
printf("a + 1L = %ld \t sizeof (a + 1L) = %lu\n", a + 1L, sizeof (a + 1L));

a = -1;
printf("a + 1 = %d \t sizeof (a + 1) = %lu\n", a + 1, sizeof (a + 1));
printf("a + 1L = %ld \t sizeof (a + 1) = %lu\n", a + 1L, sizeof (a + 1L));  //why a + 1L does not yield long integer ?

return 0;
}  

This results in the following output:

a + 1 = -2147483648   sizeof (a + 1) = 4  
a + 1L = 2147483648   sizeof (a + 1L) = 8  
a + 1 = 0    sizeof (a + 1) = 4  
a + 1L = 0   sizeof (a + 1) = 8

Why does a + 1L in last line yield 0 instead of a long integer as 4294967296 ?

rootkea
  • 1,474
  • 2
  • 12
  • 32

2 Answers2

5

why a + 1L in last line does not yield long integer as 4294967296 ?

Because converting the int -1 to a long int results in the long int with value -1, and -1 + 1 = 0.

Converting -1 to another type would only result in 4294967295 if the target type is an unsigned 32-bit type (usually, unsigned int is such, generally, uint32_t, if provided). But then, adding 1 to the value would wrap to 0.

Thus to obtain 4294967296, you would need an intermediate cast,

(uint32_t)a + 1L

so that -1 is first converted to the uint32_t with value 4294967295, and that is then converted to long.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Oh ! And I thought `int` -1 gets promoted to `long int` simply by appending extra 0's thereby getting `long int` as 4294967295. – rootkea Feb 07 '13 at 10:32
  • 1
    No, the arithmetic conversions preserve the value if it can be represented in the target type. So if you convert a value from a signed integer type to a larger signed integer type, you get sign-extension (if the representation is two's complement, as is almost universally the case nowadays). – Daniel Fischer Feb 07 '13 at 10:37
  • Hey @Daniel, have a look at this code: `short s = -1;` `printf("s = %hd\n", s);` `printf("s = %d\n", s);` `printf("s = %ld\n", s);` It gave me output as `s = -1` `s = -1` `s = 4294967295` In last line why `4294967295` and not `-1` as while promoting C preserves the value of a variable ? – rootkea Feb 07 '13 at 12:48
  • @rootkea You mustn't use `%ld` with a `short` argument, that's undefined behaviour. What **probably** happened is: `s` is converted to `int` when passing it to `printf` (the default argument promotion for variadic functions), giving 32 1 bits. With the `%ld` format, `printf` grabbed 64 bits from the register it expects the argument in [assuming usual x86_64 behaviour], and the other 32 bits were all 0 (normal when you load a 32-bit value in a 64-bit register), so you got `2^32-1` printed. – Daniel Fischer Feb 07 '13 at 13:13
1

In the first case: 2147483647 is a 32 bit signed value with hex representation 0x7fffffff. Adding 1 to it gives you a 32 bit value, hex 0x80000000, which is -2147483648 in 32 bit signed int (due to overflow) and a value of 2147483648 if considered as a 64 bit signed int.

In the second case: -1 is a 32 bit signed value with hex representation 0xffffffff. Adding 1 to it gives you a 32 bit value, hex 0x00000000, which is 0 in signed int.

When you add 1 to it in 64 bit, a sign extension first happens, so you really add 0xFFFFFFFFFFFFFFFF and 0x0000000000000001, the sum is 0 as expected.

There isn't an ambiguity if you consider the sign extension.