I am using Ubuntu 16.04.5 and GCC version 5.4.0.
I was playing with sizeof()
operator, wrote the code below:
#include <stdio.h>
int main(int argc, char *argv[]){
long int mylint = 31331313131.1313;
printf("size of long int is %d\n", sizeof(mylint));
printf("size of long int is %d\n", sizeof(long int));
return 0;
}
I tried to compile using gcc -o ... ...
command and was expecting:
size of long int is 8
size of long int is 8
But I got the following error:
fl_double_lint.c: In function ‘main’:
fl_double_lint.c:11:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("size of long int is %d\n", sizeof(mylint));
^
fl_double_lint.c:12:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("size of long int is %d\n", sizeof(long int));
When I use %ld
instead it works as expected. Why sizeof()
is not working with %d
? (Why 'long unsigned int
' but not 'int
'?)
Edit: I know that many questions were asked regarding output of sizeof() operator (as suggested in comments). However, they do not answer the question of why using %d
does not work (i.e. does not give any result). I know it is not correct format, but whenever we have a char
type variable using %d
we can get equivalent int
result, this is also the case for short, uint8_t, uint16_t, uint32_t (generally for types with equal or less than 32 bit). The following code works:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char *argv[]){
char mychar = 'd';
uint32_t myuint32 = 32;
uint16_t myuint16 = 16;
uint8_t myuint8 = 8;
short myshort = 26945;
int myint = 100;
printf("integer equivalent of mychar is %d\n", mychar);
printf("integer equivalent of myuint8 is %d\n", myuint8);
printf("integer equivalent of myuint16 is %d\n", myuint16);
printf("integer equivalent of myuint32 is %d\n", myuint32);
printf("character equivalent of myint is %c\n", myint);
printf("integer equivalent of myshort is %d\n", myshort);
return 0;
}
The result is:
integer equivalent of mychar is 100
integer equivalent of myuint8 is 8
integer equivalent of myuint16 is 16
integer equivalent of myuint32 is 32
character equivalent of myint is d
integer equivalent of myshort is 26945
And now I discovered that %d
does not work for any variable that needs larger than 32 bit to be stored. After considering this question I have some idea about implementation dependence of size_t
, maybe in my system it was unsigned long
(%ld
also giving the result proves it). So maybe if size_t
was an unsigned int
in my system I would get a result, is it true?
As it can be seen from the code above, %c
decodes the last 8 bits of int
as a character, why %d
does not do the same (i.e. decode the last 32 bits of content of size_t
variable as it was int
? I believe if it would do so we could get the same result for small enough numbers, and this was what I meant when I initially asked the question).
long unsigned int
' but not 'int
'?" What sense would negative value, returned fromsizeof
make? – Watchman"%ld"
is also wrong. Thesizeof
operator returns a value of typesize_t
, and to print it withprintf
(and family) you should use"%zu"
. Or since you also tagged this question with the very different C++ language, just usestd::cout << sizeof(something)
. – Bridgessize_t
appears to belong unsigned int
on your system, but it doesn't have to. Can be unsigned short or unsigned int or whatever, as long as it can represent the size of objects on that platform – Ductilemyuint32
is anuint32_t
which must be printed usingPRIu32
. Remember int is not always 32 bits, and printing an unsigned type with signed format specifier is still UB. printf format specifiers for uint32_t and size_t – Ductilewhy %d does not do the same (i.e. decode the last 32 bits of content of size_t variable as it was int?)
C doesn't work that way. Type sizes are not fixed and vararg functions doesn't know what size a parameter is. On platforms where those are on stack then if you specify a different type different from what you give it then you can mess up the stack when printf pops a different number of bytes for that argument. As said, use the correct specifier and don't wonder why it works here and not there – Ductile