[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