How sizeof operator works in C? [duplicate] - c

This question already has an answer here:
Output data type of sizeof() operator
(1 answer)
Closed 4 years ago.
In this below code:
#include<stdio.h>
int main(void)
{
printf("%d",sizeof(int));
return 0;
}
When compiled on gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 compiler it gives warning:
format ‘%d’ expects argument of type ‘int’, but argument 2 has type
‘long unsigned int’ [-Wformat=] printf("%d",sizeof(int));
Why I am getting this warning? Is it that return type of sizeof is 'long unsigned int' ?
When I replaced '%d' with '%ld' the warning went.

The sizeof operator is processed at compile time (and can be applied on both types and expressions). It gives some constant* of type size_t. On your system (and mine Debian/Linux/x86-64 also) sizeof(int) is (size_t)4. That size_t type is often typedef-ed in some type like unsigned long (but what integral type it actually is depends upon the implementation). You could code
printf("%d", (int)sizeof(int));
or (since printf understands the %zd or %zu control format string for size_t)
printf("%zu", sizeof(int));
For maximum portability, use %zu (not %ld) for printing size_t (because you might find systems or configurations on which size_t is unsigned int etc...).
Note *: sizeof is always constant, except for VLA

Related

Machine-independent printf() of int64_t? [duplicate]

This question already has answers here:
How to portably print a int64_t type in C
(7 answers)
Closed 4 months ago.
Consider the following snippet, compiled with gcc -Wall for two different architectures:
int64_t x;
printf("A: %ld\n", x);
printf("B: %lld\n", x);
When compiling for a 32 bit machine, the compiler complains about "A":
format '%ld' expects argument of type 'long int', but argument 2 has type 'int64_t' {aka 'long long int'}
When compiling for a 64 bit machine, the compiler complains about "B":
format '%lld' expects argument of type 'long long int', but argument 2 has type 'int64_t' {aka 'long int'}
The question: What is a sensible machine-independent way to printf() int64_t?
The header inttypes.h contains portable conversion specifiers for printf and scanf family of functions. (It also internally includes stdint.h.)
#include <inttypes.h>
int64_t x = ...;
printf("%"PRIi64, x);
See the C standard C17 7.8.1 for details.

what does mean this exception ? format %d expects argument of type 'int', but argument 2 has type 'long long unsigned int' [-Wformat] [duplicate]

This question already has answers here:
How should I print types like off_t and size_t?
(10 answers)
Closed 2 years ago.
I'm a student trying to learn C and C++, I've got a problem with the specifier %d I dont't understand the exception that is written in the console, It's writing
The format %d expects argument of type 'int', but argument 2 has type 'long long unsigned int' [-Wformat]
Here is the code :
#include<stdio.h>
#include<stdlib.h>
int main()
{
short int u=1;
int v=2;
long int w=3;
char x='x';
float y=4;
double z=5;
long double a=6;
long b=7;
printf("short int:%d\n",sizeof(u));
printf("int:%d octets\n",sizeof(v));
printf("long int:%d octets\n",sizeof(w));
printf("char:%d octets\n",sizeof(x));
printf("float:%d octets\n",sizeof(y));
printf("double:%d octets\n",sizeof(z));
printf("long double:%d octets\n",sizeof(a));
printf("long:%d octets\n",sizeof(b));
return 0;
}
The type of the value returned by the operator sizeof is the unsigned integer type size_t The conversion specifier d is used to output values of the type int. You have to use the conversion specifier zu. Otherwise you will get undefined behavior.
For example
printf("short int:%zu\n",sizeof(u));
From the C Standard (7.21.6.1 The fprintf function)
9 If a conversion specification is invalid, the behavior is
undefined.275) If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
The sizeof operator returns a size_t type. This is always unsigned and, on your platform, is a long long unsigned int; on other platforms, it may be just unsigned long or, indeed, some other (unsigned) integer type.
Use the %zu format specifier for arguments of this type; this will work whatever the actual size_t type definition happens to be.

Why do I have to use %ld when referring to the size of an int variable?

I define an int like this:
int a;
When I want to lookup the size of this int, I have to use the format specifier %ld like this:
printf("int size is %ld\n", sizeof(a));
When I use %d as the format specifier, I get the following error:
foo.c:7:10: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("int size is %d\n", sizeof(a));
The question is, why is the result of sizeof() defined as long unsigned int when the parameter of the function is an int?
The type of sizeof(anything) is size_t, which is some unsigned integral constant. To print it, you should be using %zu.
According to the C Standard (6.5.3.4 The sizeof and alignof operators)
5 The value of the result of both operators is implementation-defined,
and its type (an unsigned integer type) is size_t, defined in
<stddef.h> (and other headers).
and (7.19 Common definitions <stddef.h>)
size_t which is the unsigned integer type of the result of the
sizeof operator;
and (7.21.6.1 The fprintf function)
z Specifies that a following d, i, o, u, x, or X conversion specifier
applies to a size_t....
Thus it would be more correctly to write
printf( "int size is %zu\n", sizeof( a ) );
^^^
It is not important what type of an object the operator sizeof is applied to. It returns the number of bytes occupied by an object of the given type and the returned number has type size_t.
Your compiler issues a warning because in your system type size_t is defined like unsigned long int but you are using signed int. It seems does not issue a warning when you use format specifier %ld because the rank of the signed long int type is equal to the rank of the unsigned long int type that corresponds to size_t.
"when the parameter of the function is an int?"
First off, sizeof is an operator, not a function.
Second, why do you think its result type should be the same as its argument type? What if you want to get the size of a struct? or an array? or a pointer? How would it be supposed to yield the size of a struct as a struct? It just doesn't make sense.
It yields a size, so the type of its result is size_t, that you should print using %zu.
sizeof gives the number of storage units taken up by the operand. The result type is size_t, which is an unsigned type wide enough to represent the size of the largest object the system is capable of storing. The type of the operand doesn't affect the type of the result.
With C89 compilers, you can print a size_t value with %ld and cast the argument to unsigned long:
printf( "sizeof x = %ld\n", (unsigned long) sizeof x );
With C99 and later compilers, use %zu:
printf( "sizeof x = %zu\n", sizeof x );
%zu is not portable; it requires a C99 library. For instance, MinGW:
$ cat zu.c
#include <stdio.h>
int main(void)
{
printf("%zu\n", sizeof (int));
return 0;
}
$ gcc zu.c -o zu
$ ./zu.exe
zu
Oops! The characters zu printed literally, and the size argument was ignored.
For printing types which you know are reasonably small, cast the size to int or unsigned, and use the %d or %u conversion specifier:
printf("sizeof int == %d\n", (int) sizeof (int));
If there is any possibility that the size of an object might not fit into type int, try unsigned long int:
printf("sizeof int == %lu\n", (unsigned long) sizeof object);
This is probably only necessary on systems with a small int, like 16 bits, such that int only goes up to 32767 and unsigned int to 65535, and yet there can be objects whose sizes exceed these values.
If you're sure that the program needs only to be portable to targets that support C99, then %zu it is.

Getting Warning When Using SizeOf [duplicate]

This question already has answers here:
'%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=] [duplicate]
(3 answers)
Closed 9 years ago.
I am getting a warning warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
I am writing a very basic program which gives the size of the data type but in the Linux environment I am getting this warning whereas in Visual Studio, the program works without any warning. The source code is as below :-
#include<stdio.h>
int main()
{
int a;
printf("\nThe Size Of Integer A Is = \t%d", sizeof(a));
return 0;
}
Answer will be appreciated and also can anyone tell me a proper way of solving such kind of warnings as I am new to this C and it's standard.
sizeof returns size_t type. Use %zu specifier to print the value of sizeof.
printf("\nThe Size Of Integer A Is = \t%zu", sizeof(a));
C11 6.5.3.4 The sizeof and _Alignof operators:
5 The value of the result of both operators is implementation-defined, and its type (an
unsigned integer type) is size_t, defined in <stddef.h> (and other headers).
NOTE: As loreb pointed out in his comment that when you will compile your code in Windows, then most probably you will get the warning like:
[Warning] unknown conversion type character 'z' in format [-Wformat]
[Warning] too many arguments for format [-Wformat-extra-args]
sizeof return size_t and not int
Use %zu in printf
In C99 the correct format for a size_t variable is %zu.
Use:
printf("\nThe Size Of Integer A Is = \t%zu", sizeof(a));

printing size_t: format '%lu' expects argument of type 'long unsigned int'

I try to print size_t by casting to unsigned long (as suggested in the book "C programming a modern approach) like the following:
printf("size:%lu, bsize:%lu", (unsigned long)size, (unsigned long)bsize);
printf("size:%lu, bsize:%lu", ((unsigned long)size), ((unsigned long)bsize));
The first line would give me warning (gcc):
warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t' [-Wformat]
What's the difference between the first line and the second line? All I did was putting extra parenthesis, what exactly does that do?
I know I can use "%z" but this problem bugs me.
Assuming there are no ugly #defines around
printf("size:%lu, bsize:%lu", (unsigned long)size, (unsigned long)bsize);
and
printf("size:%lu, bsize:%lu", ((unsigned long)size), ((unsigned long)bsize));
are equivalent.
And therefore they shall result in the same code/warnings/errors.
If they don't, there is something broken.

Resources