This question already has answers here:
Why is sizeof considered an operator?
(10 answers)
Closed 8 years ago.
In c, we are using the sizeof() for getting the size of the datatypes. So
how it is defined. It is a macro or a function.
Because we can use that as two ways,
sizeof int
and
sizeof(int)
so how this is defined in header file.
It's neither. It's a built-in operator, whose value is computed at compile-time unless the argument is the name of a variable-length array (added in C99).
The parentheses that you often see are not part of the "call", since sizeof is not a function. They are part of the argument, and are only needed when the argument is a cast expression, i.e. the name of a type enclosed in parentheses.
I personally recommend against using sizeof with a type name as the argument whenever possible, since it's usually not needed, and creates a disconnect/de-coupling which can lead to errors.
Consider something like this:
float *vector = malloc(100 * sizeof(double));
The above, of course, contains a bug: if float is smaller than double, it will waste a lot of memory. It's easy to imagine ending up with something like the above, if vector started out as an array of double but was later changed to float. To protect aginst this, I always write:
float *vector = malloc(10 * sizeof *vector);
The above uses the argument *vector (an expression of type float) to sizeof, which is not a type name so no parentheses are needed. It also "locks" the size of the element to the pointer used to hold it, which is safer.
Sizeof is neither a macro nor a function.Its a operator which is evaluated at compile time.
Macros evaluated during pr-processing phase.
As pointed out by #Yu Hao Variable length arrays is the only exception.
For More Understanding solve this;
#include<stdio.h>
char func(char x)
{
x++;
return x;
}
int main()
{
printf("%zu", sizeof(func(3)));
return 0;
}
A) 1 B)2 C)3 D)4
From ISO/IEC9899
6.5.3.4 The sizeof operator
Constraints
1 The sizeof operator shall not be applied to an expression that has function type or an
incomplete type, to the parenthesized name of such a type, or to an expression that
designates a bit-field member.
So it is neither a macro nor a function.Its a operator!
and the way it is handled is a thing of the compiler.
But regarding to compile time and runtime determination the standard says:
Semantics
2 The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. The result is an integer. If the type of the operand is a variable length array
type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.
So it is even given by standard that it mus be determined on compile time excepting the VLA case.
Syntax
sizeof( type )
List sizeof expression
Both versions return a constant of type std::size_t.
Explanation
returns size in bytes of the object representation of type.
returns size in bytes of the object representation of the type, that
would be returned by expression, if evaluated.
The unary operator sizeof is used to calculate the size of any datatype, measured in the number of bytes required to represent the type.
In many programs, there are situations where it is useful to know the size of a particular datatype (one of the most common examples is dynamic memory allocation using the library function malloc). Though for any given implementation of C or C++ the size of a particular datatype is constant, the sizes of even primitive types in C and C++ are implementation-defined (that is, not precisely defined by the standard). This can cause problems when trying to allocate a block of memory of the appropriate size. For example, say a programmer wants to allocate a block of memory big enough to hold ten variables of type int. Because our hypothetical programmer doesn't know the exact size of type int, the programmer doesn't know how many bytes to ask malloc for. Therefore, it is necessary to use sizeof:
Related
This question already has answers here:
Why does sizeof(x++) not increment x?
(10 answers)
Closed 7 years ago.
The C code likes this:
#include <stdio.h>
#include <unistd.h>
#define DIM(a) (sizeof(a)/sizeof(a[0]))
struct obj
{
int a[1];
};
int main()
{
struct obj *p = NULL;
printf("%d\n",DIM(p->a));
return 0;
}
This object pointer p is NULL, so, i think this p->a is illegal.
But i have tested this code in Ubuntu14.04, it can execute correctly. So, I want to know why...
Note: the original code had int a[0] above but I've changed that to int a[1] since everyone seems to be hung up on that rather than the actual question, which is:
Is the expression sizeof(p->a) valid when p is equal to NULL?
Because sizeof is a compile time construction, it does not depend on evaluating the input. sizeof(p->a) gets evaluated based on the declared type of the member p::a solely, and becomes a constant in the executable. So the fact that p points to null makes no difference.
The runtime value of p plays absolutely no role in the expression sizeof(p->a).
In C and C++, sizeof is an operator and not a function. It can be applied to either a type-id or an expression. Except in the case that of an expression and the expression is a variable-length array (new in C99) (as pointed out by paxdiablo), the expression is an unevaluated operand and the result is the same as if you had taken sizeof against the type of that expression instead. (C.f. C11 references due to paxdiablo below, C++14 working draft 5.3.3.1)
First up, if you want truly portable code, you shouldn't be attempting to create an array of size zero1, as you did in your original question, now fixed. But, since it's not really relevant to your question of whether sizeof(p->a) is valid when p == NULL, we can ignore it for now.
From C11 section 6.5.3.4 The sizeof and _Alignof operators (my bold):
2/ The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
Therefore no evaluation of the operand is done unless it's a variable length array (which your example is not). Only the type itself is used to figure out the size.
1 For the language lawyers out there, C11 states in 6.7.6.2 Array declarators (my bold):
1/ In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero.
However, since that's in the constraints section (where shall and shall not do not involve undefined behaviour), it simply means the program itself is not strictly conforming. It's still covered by the standard itself.
This code contains a constraint violation in ISO C because of:
struct obj
{
int a[0];
};
Zero-sized arrays are not permitted anywhere. Therefore the C standard does not define the behaviour of this program (although there seems to be some debate about that).
The code can only "run correctly" if your compiler implements a non-standard extension to allow zero-sized arrays.
Extensions must be documented (C11 4/8), so hopefully your compiler's documentation defines its behaviour for struct obj (a zero-sized struct?) and the value of sizeof p->a, and whether or not sizeof evaluates its operand when the operand denotes a zero-sized array.
sizeof() doesn't care a thing about the content of anything, it merely looks at the resulting type of the expression.
Since C99 and variable length arrays, it is computed at run time when a variable length array is part of the expression in the sizeof operand.Otherwise, the operand is not evaluated and the result is an integer constant
Zero-size array declarations within structs was never permitted by any C standard, but some older compilers allowed it before it became standard for compilers to allow incomplete array declarations with empty brackets(flexible array members).
I have tried searching this out a lot. Static arrays are generally stored in a stack and their size is determined during compilation time.
Ex:
int main()
{
int n;
scanf("%d", &n);
int array[n];
printf("%u", sizeof(array));
return 0;
}
The size of array changes for different values of n. Hence, shouldn't the array here be stored in a heap as the size is determined at run-time? Have been confused about this. Please help. Thank You!
shouldn't the array here be stored in a heap as the size is determined at run-time?
It could, but it is not the only way to do it. C compiler is smart enough to defer the allocation of memory for this variable-length array in the automatic memory (commonly known as "the stack") to the point in code where the size of the array becomes known.
In order to make this possible, a related trick for sizeof needed to be created. Usually, sizeof is evaluated at compile-time; variable-length arrays, however, changed that, requiring the sizeof expressions on VLAs to be evaluated at runtime. Again, the compiler provides the "enabling technology" for that by storing the actual size of your VLA in a separate hidden location in memory.
See what standard says about this special case:
C11: 6.5.3.4 (p2):
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
This question already has answers here:
Why is the size of a function in C always 1 byte?
(4 answers)
Closed 9 years ago.
I always understood that in C, func and &func were equivalent. I assume they should both be of type pointer, which is 8 bytes on my Win64 system. However, I just tried this:
#include <stdio.h>
int func(int x, int y)
{
printf("hello\n");
}
int main()
{
printf("%d, %d\n", sizeof(&func), sizeof(func));
return 0;
}
And expecting to get the output 8, 8 was surprised to get 8, 1 instead.
Why is this? What type exactly is func? It seems to be of type char or some equivalent.
What is going on here?
I compiled this with gcc -std=c99 if it makes a difference.
What type is a function name in C?
A function name or function designator has a function type. When it is used in an expression, except when it is the operand of sizeof or & operator, it is converted from type "function returning type" to type "pointer to a function returning type". (This is specified in C99, 6.3.2.1p4).
Now
sizeof(func)
is not valid C as sizeof is not allowed with an operand of function type. This is specified in the constraints of the sizeof operator:
(C99, 6.5.3.4p1 Constraints) "The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member."
But
sizeof(func)
is allowed in GNU C.
There is a GNU extension in GNU C that allows it and in GNU C sizeof with an operand of function type yields 1:
6.23 Arithmetic on void- and Function-Pointers
[...] sizeof is also allowed on void and on function types, and returns 1.
http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
Given:
int func(int x, int y) { /* ... */ }
the expression func is of function type. Specifically, it's of type int(int, int), which is C's syntax for the type "function with two int parameters returning int. (You won't often see that particular syntax, since it's not common to refer to function types directly.)
In most contexts, an expression of function type is implicitly converted to a pointer to the function; in this case, the pointer is of type int(*)(int, int).
The contexts in which this implicit conversion does not occur are:
When the expression is the operand of unary &; in that case, &func yields the address of the function (just as func by itself usually does); and
When the expression is the operand of sizeof. Without this exception, sizeof func would yield the size of a function pointer. Instead, it's a constraint violation, requiring a diagnostic from the compiler.
(A side note: This conversion does happen when the function name is used in a function call. The () "operator" (the standard doesn't call it that) requires a prefix of pointer-to-function type.)
gcc happens to have a non-standard extension; it permits pointer arithmetic on function pointers and on type void*, acting like pointer arithmetic on char* pointers (i.e., it operates in units of bytes). Unfortunately, IMHO, gcc did this via a kludge, setting the size of function types and of type void to 1. That's why you get sizeof func == 1; if you enable one of the standard conforming modes (e.g., gcc -std=c99 -pedantic), you'll get a warning.
Incidentally, don't use %d to print the result of sizeof. sizeof yields a result of type size_t. If your implementation supports it (C99 or later), use %zu; if not, you need to use a cast to explicitly convert the size_t value to something that you can print. For example:
printf("%lu\n", (unsigned long)sizeof &func);
What type is a function name in C?
It's of a function type.
I always understood that in C, func and &func were equivalent
Well, they are not "equivalent". A function does, however, decay into a pointer-to-function.
I assume they should both be of type pointer
That's an incorrect assumption.
And expecting to get the output 8, 8 was surprised to get 8, 1 instead. Why is this?
Because 1. it's UB if it compiles, 2. it shouldn't even compile in first place, and as such, your program is free to do anything.
Names do not have a type in C. Some kinds of names denote entities that have type, such as typedef names, objects or functions. Other kinds of names denote entities that do not have a type, such as preprocessor symbols or goto labels. Yet other kind of names simply denote types themselves, namely typedef names.
The name of a function denotes an entity that has function type. That function type includes the return type, and (possibly incomplete) information about the parameters.
When functions are used as values, they are always manipulated as pointer-to-function types. A function as such cannot be passed around in a portable C program, but a pointer to a function can be.
Conceptually, even in a direct call like foo(), what happens is that foo, an expression denoting a function, upon evaluation is implicitly converted to a pointer-to-function value. The () function call postfix operator then invokes the function by means of this pointer.
There is a rule that an expression that has function type produces a pointer value, except if that expression is the operand of the & (address of) or of the sizeof operator. func and &func are only equivalent in the sense that they produce the same value. func produces a pointer value implicitly. &func suppresses the implicit generation of a pointer (func is the operand of & and so the conversion is suppressed), but then & takes the address.
So you can see that sizeof &func and sizeof func are different. The former takes the size of a pointer, and the latter tries to take the size of a function.
Taking the size of a function is a constraint violation in C: it requires a diagnostic from an implementation that conforms to the standard. If the program still translates and a value of 1 is produced when it is run, that is "bonus" behavior specific to your language implementation. It is not in the standard language.
Sizeof operator is compile time operator. converts sizeof expression with constant result values during compile time. [Exception variadic templates c99]
Normally compiler fixes size for variables at compile time. for array n.
But when i print sizeof array it gives correct size?
is this code allots memory at compile time for n?
How sizeof is evaluated then?
how about the array a[] in function?
int fun(int n)
{
char a[n+3];
return sizeof(a);
}
int
main( )
{
int i;
while(i!=-1){
scanf("%d",&i);
int n[i];
printf("\nsize: %d %d\n",fun(3),sizeof n);
}
}
when i try this :
sizeof prints size of n correctly [(sizeof (int)) * i] but the function gives wrong results always 6?
How sizeof is implemented and calculates size (for float,int,...datatypes , variables, array, ...) ?
Any code is appreciated!
As you mention, sizeof calculations are normally made at compile time, by the compiler. That's not always true (for example, C99/C11 variable length arrays), but it's a reasonable approximation.
Since the compiler knows (or decides) the size of every type, it can just make a simple constant substitution during compilation.
For your examples, a and n are both variable length arrays, and the sizeof operator is applied at runtime.
From C11, Section 6.5.3.4 The sizeof and _Alignof operators, paragraph 2:
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
Editorial note: sizeof returns a size_t, not an int, so you should use a %zu format specifier instead of %d. Your compiler may warn you if you turn on the appropriate flags.
Wikipedia explains the implementation of sizeof pretty well, See here for detail.
It is the responsibility of compilers to implement the sizeof operator correctly for each target platform. In many cases, there will be an official Application Binary Interface (ABI) document for the platform, specifying formats, padding, and alignment for the data types, to which the compiler must conform. In most cases, sizeof is a compile-time operator, which means that during compilation sizeof expressions get replaced by constant result-values. However, sizeof applied to a variable length array, introduced in C99, requires computation during program execution.`
When the operand of sizeof is not a variable-length array (VLA), then it sizeof not really "calculate" anything. The result is immediately known to the compiler as a compile-time constant. That constant is substituted in place of sizeof during compilation.
If the operand is VLA, then the compiler simply generates code that retrieves the size information from the VLA itself. So, yes, in general case a typical implementation does store the size of the VLA inside the VLA itself. In your example that means that the memory allotted for a will also include a location to store the n + 3 value.
The compiler can, of course, optimize this evaluation in obvious cases and even replace it with compile-time constant in the most obvious cases. In your example the compiler might be smart enough not to retrieve the size from the array a, but instead immediately realize that the size is equal to n + 3.
Why is sizeof considered an operator and not a function?
What property is necessary to qualify as an operator?
Because the C standard says so, and it gets the only vote.
As consequences:
The operand of sizeof can be a parenthesised type, sizeof (int), instead of an object expression.
The parentheses are unnecessary: int a; printf("%d\n", sizeof a); is perfectly fine. They're often seen, firstly because they're needed as part of a type cast expression, and secondly because sizeof has very high precedence, so sizeof a + b isn't the same as sizeof (a+b). But they aren't part of the invocation of sizeof, they're part of the operand.
You can't take the address of sizeof.
The expression which is the operand of sizeof is not evaluated at runtime (sizeof a++ does not modify a).
The expression which is the operand of sizeof can have any type except void, or function types. Indeed, that's kind of the point of sizeof.
A function would differ on all those points. There are probably other differences between a function and a unary operator, but I think that's enough to show why sizeof could not be a function even if there was a reason to want it to be.
It can be used as a compile-time constant, which is only possible if it's an operator rather than a function. For instance:
union foo {
int i;
char c[sizeof(int)];
};
Syntactically if it weren't an operator then it would have to be a preprocessor macro since functions can't take types as arguments. That would be a difficult macro to implement since sizeof can take both types and variables as an argument.
Because the C standard says so, and it gets the only vote.
And the standard is probably correct because sizeof takes a type and
In general, if either the domain or codomain (or both) of a function contains elements significantly more complex than real numbers, that function is referred to as an operator. Conversely, if neither the domain nor the codomain of a function contain elements more complicated than real numbers, that function is likely to be referred to simply as a function. Trigonometric functions such as cosine are examples of the latter case.
Additionally, when functions are used so often that they have evolved faster or easier notations than the generic F(x,y,z,...) form, the resulting special forms are also called operators. Examples include infix operators such as addition "+" and division "/", and postfix operators such as factorial "!". This usage is unrelated to the complexity of the entities involved.
(Wikipedia)
Because it's not a function. You can use it like that:
int a;
printf("%d\n", sizeof a);
Function does have entry point, code, etc. Function is to be run at runtime (or inlined), sizeof has to be determined at compile-time.
sizeof operator is compile time entity not runtime and don't need parenthesis like a function. When code is compiled then it replace the value with the size of that variable at compile time but in function after function gets execute then we will know the returning value.
Because:
when you pass a value to a function, the size of the object is not passed to the function, so a sizeof "function" would have no way of determining the size
in C, functions can only accept one type of argument; sizeof() needs to accept all sorts of differnet things (variables as well as types! You can't pass a type to a function in C)
calling a function involves making a copy of the arguments and other unnecessary overhead
There is small diference from function - value of sizeof is resolved on compile time, but not at runtime!
Because it is a compile-time operator that, in order to calculate the size of an object, requires type information that is only available at compile-time. This doesn't hold for C++.
sizeof() operator is a compile time would be occurrence. It can be used to determine the parameters or arguments.
Sizeof(), I think obviously it's both a function and an operator. Why? Because a function holds parentheses for entry at the stage of entry. But mainly also an operator cause operators are action character, therefore sizeof is an action statement that acts on the operand in the parentheses.