[C-prog-lang-l] Arithmetic conversions and sizes of types in limits.h
Jan Pechanec
jp at devnull.cz
Wed Mar 16 07:40:52 CET 2022
On Tue, 15 Mar 2022, Walter Herold Veedla wrote:
> Hello,
>
> I was thinking about the integer promotion topic that we talked about this
> Monday and I think I have an interesting observation that was not explicitly
> mentioned in class as well as a question.
>
> I dug around in limits.h
> (https://opensource.apple.com/source/xnu/xnu-201/EXTERNAL_HEADERS/machine/limits.h.auto.html)
> and noticed the asymmetric definition of INT_MAX and INT_MIN:
>
> #define __INT_MAX__ 2147483647
> #define INT_MIN (-INT_MAX-1)
>
> Which puzzled me for a bit and made me think of the question why we do not
> define
>
> #define INT_MIN -2147483648
>
> instead? After all, this is the value you get when you print out INT_MIN. My
> hunch is that what is mentioned in notes5.md under integer promotion (but this
> is not integer *promotion*, is it?) is also happening here and the value
> 2147483648 does not fit the value of integer due to the asymmetrical range of
> two's complement and is first converted to long, before the unary minus is
> applied. Is that correct?
>
>
> Secondly, whereas INT_MAX and INT_MIN are defined in this asymmetric way,
> CHAR_MIN, CHAR_MAX, SHRT_MIN, SHRT_MAX are not, see:
>
> #define CHAR_MAX 127
> #define CHAR_MIN (-128)
> #define SHRT_MAX 32767
> #define SHRT_MIN (-32768)
>
> This is really strange, furthermore when printing the sizes of these quantities
> they do not correspond to the sizes of the types, but even CHAR_MAX is 4 bytes.
> See the following output:
>
> cc -std=c99 -Wall -Wextra -pedantic limits_test.c && ./a.out | 1
> #include <stdio.h>
> sizeof(short) = 2 | 2
> #include <limits.h>
> sizeof(int) = 4 | 3
> sizeof(long) = 8 | 4 int
> INT_MAX = 2147483647 (4 bytes) | 5
> main(void)
> 8 = sizeof(-2147483648) | 6 {
> 4 = sizeof(-INT_MAX-1) | 7 printf("sizeof(short)\t= %zu\n",
> sizeof(short));
> | 8 printf("sizeof(int)\t= %zu\n", sizeof(int));
> | 9 printf("sizeof(long)\t= %zu\n", sizeof(long));
> SHRT_MAX = 32767 (4 bytes) | 10
> 4 = sizeof(-32768) | 11 // The below is -INT_MAX-1 written directly
> 4 = sizeof(-SHRT_MAX-1) | 12 printf("INT_MAX = %d (%zu bytes)\n",
> INT_MAX, sizeof(INT_MAX));
> |
> 13 printf("%zu = sizeof(-2147483648)\n", sizeof(-2147483648));
> |
> 14 printf("%zu = sizeof(-INT_MAX-1)\n", sizeof(-INT_MAX-1));
> CHAR_MAX = 127 (4 bytes) | 15
> 4 = sizeof(-32768) | 16 printf("\n\n");
> 4 = sizeof(-SHRT_MAX-1) | 17
> |
> 18 printf("SHRT_MAX = %d (%zu bytes)\n", SHRT_MAX, sizeof(SHRT_MAX));
> |
> 19 printf("%zu = sizeof(-32768)\n", sizeof(-32768));
> |
> 20 printf("%zu = sizeof(-SHRT_MAX-1)\n", sizeof(-SHRT_MAX-1));
> | 21
> |
> 22 printf("\n\n");
> | 23
> |
> 24 printf("CHAR_MAX = %d (%zu bytes)\n", CHAR_MAX, sizeof(CHAR_MAX));
> |
> 25 printf("%zu = sizeof(-32768)\n", sizeof(-32768));
> |
> 26 printf("%zu = sizeof(-SHRT_MAX-1)\n", sizeof(-SHRT_MAX-1));
> | 27 }
>
> What is going on here?
Hi Walter,
excellent observations, thank you for bringing that up. Look at the
following code and its results:
janp:t490:~$ cat main.c
#include <stdio.h>
#include <limits.h>
#define MYINT_MIN -2147483648
#define MYINT_MIN2 (-INT_MAX - 1)
int
main(void)
{
printf("%zu\n", sizeof (MYINT_MIN));
printf("%zu\n", sizeof (MYINT_MIN2));
}
janp:t490:~$ cc main.c
janp:t490:~$ ./a.out
8
4
Can you answer your questions now?
Also see the C99 spec, 6.4.4.1 Integer constants.
Cheers,
Jan
>
> If for some reason the output of the program arrives mis-formatted, I am also
> attaching a .txt file of the output with this e-mail.
>
>
> Anyways, I'd be happy to hear Your thoughts.
>
> Kind regards
>
> Walter Herold Veedla
>
>
--
Jan Pechanec <jp (at) devnull (dot) cz>
http://www.devnull.cz
More information about the c-prog-lang-l
mailing list