why sizeof(function_name) is 1 [duplicate] - c

This question already has answers here:
Logic behind sizeof() for character constants and function names [duplicate]
(2 answers)
Closed 9 years ago.
Why is the result of:
sizeof(function_name)?
1? Somebody in community said that sizeof(main) is 1 but sizeof(main()) is 4. Here main is returning int, so it is returning 4. but if we do declaration as char main() instead of int main() it will return 1 only.

It's illegal to use sizeof on a function.
C99 §6.5.3.4 The sizeof operator
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 if foo is the function name, sizeof(foo) is illegal, but sizeof(foo()) applies sizeof on the return value of foo(). main() returns int in standard C, it's 4 bytes on most machines today.

sizeof(char) equals 1, always and everywhere.
So everything declared char would do also, and this already at compile-time.

Related

Behavior of "comma" operator in sizeof() operator In C [duplicate]

This question already has answers here:
Why do I get different results when I apply sizeof operator?
(2 answers)
Closed 5 years ago.
I wrote the code about sizeof operator. If I write something like:
#include <stdio.h>
int main() {
char a[20];
printf("%zu\n", sizeof(a));
return 0;
}
Output:
20 // Ok, it's fine
But, If I use the comma operator like this:
#include <stdio.h>
int main() {
char a[20];
char b;
printf("%zu\n", sizeof(b, a));
return 0;
}
Output:
8 // Why the output 8?
So, I have a questions:
Why does compiler give an output 8 in second example?
What is the behavior of comma operator into sizeof() operator?
The comma operator has no special meaning to sizeof.
sizeof(b, a) examines the complete expression (b, a), works out the resultant type, and computes the size of that type without actually evaluating (b , a). As noted by chqrlie in comments, the () are part of the expression for which the size (of the result) is evaluated.
In this case, b is a char and a is an array. If the expression b, a was to be evaluated, b would be evaluated first, the result discarded. Then a would converted to a pointer (char *) with value equal to &a[0] which would be the result of the expression (b, a).
Since the result of b, a is of type char *, sizeof(b,a) is equal to sizeof (char *). That is an implementation defined value but, for your compiler, has a value of 8 (which probably means the code is being built as a 64-bit application).
In most cases, arrays decay into pointers. So the type of b,a with a comma operator is a char* (not a char[20] anymore). And pointers are 8 bytes on your machine.
BTW, I think that using sizeof on some comma operator is really confusing to the reader. I recommend using sizeof on simple expressions or on types.
(and I just discovered this is one of the tricky differences between C and C++; see this explanation)
C language is an lvalue-discarding language. Comma operator in C does not yield an lvalue and does not preserve "arrayness" of arrays. This means that when right-hand side operand is an array, it is immediately subjected to array-to-pointer conversion. For this reason in C the result of your comma operator is an rvalue of type char *. This is what you apply your sizeof to. And this is why you get 8 as the result, which is pointer size on your platform.
C++ language is an lvalue-preserving language. The right-hand operand of comma operator in C++ is not subjected to lvalue-to-rvalue conversion and, in case the operand is an array, it maintains its lvalueness and its array type. In C++ the result of your comma operator is an lvalue of type char[20]. This is what you apply your sizeof to. And this is why you get 20 as the result.
sizeof determines the size by the type of it's operand. In sizeof(a), a will not decay to pointer to it's first element and the type of a will be char[20]. While in sizeof(b, a), a is the right operand of comma operator and in this context it will decay to pointer to it's first element and the type of the expression b , a would be char *. Therefore, sizeof(b, a) will return size of char * data type.
In C++, result of , operator is an lvalue (unlike in C where it yields an rvalue). In that case sizeof(b, a) will return the size of array a.

Is it defined behavior to allocate memory using the variable being declared? [duplicate]

This question already has answers here:
Can "sizeof(arr[0])" lead to undefined behavior?
(5 answers)
Closed 6 years ago.
I was looking at a port of libusb today for android and I noticed this line of code:
struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd));
It seems that ipollfd is being allocated based on the size of itself which has not been completely allocated yet. My first thought would be that the behavior of this is undefined. Is that the case?
It's fine and well-defined behaviour.
sizeof gets evaluated at compile-time, and unless the operand is VLA, the operand is not evaluated. (So, no invalid-pointer dererefence, as it might look like)
To put it in other words, sizeof only needs to know the type of the operand (which is already defined).
Quoting C11, chapter §6.5.3.4
[....] 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.

Is dereferencing null pointer valid in sizeof operation [duplicate]

This question already has answers here:
Why doesn't my program seg fault when I dereference a NULL pointer inside of malloc?
(4 answers)
Closed 6 years ago.
I've come across a snippet of code that to me should crash with a segmentation fault, and yet it works without a hitch. The code in question plus relevant data structure is as follows (with associated comment found right above):
typedef struct {
double length;
unsigned char nPlaced;
unsigned char path[0];
}
RouteDefinition* Alloc_RouteDefinition()
{
// NB: The +nBags*sizeof.. trick "expands" the path[0] array in RouteDefinition
// to the path[nBags] array
RouteDefinition *def = NULL;
return (RouteDefinition*) malloc(sizeof(RouteDefinition) + nBags * sizeof(def->path[0]));
}
Why does this work? I gather that the sizeof the char* will resolve to the size of the pointer on the given architecture, but shouldn't it crash and burn while dereferencing a NULL-pointer?
Why does this work?
This works because sizeof is a compile time construct, with the exception of variable length arrays is not evaluated at all. If we look at the C99 draft standard section 6.5.3.4 The sizeof operator paragraph 2 says(emphasis mine):
[...] 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.
we also see the following example in paragraph 5 which confirms this:
double *dp = alloc(sizeof *dp);
^^^ ^
|
This is not the use of uninitialized pointer
At compile time the type of the expression with be determined in order to compute the result. We can further demonstrate this with the following example:
int x = 0 ;
printf("%zu\n", sizeof( x++ ));
which won't increment x, which is pretty neat.
Update
As I note in my answer to Why does sizeof(x++) not increment x? there is an exception to sizeof being a compile time operation and that is when it's operand is a variable length array(VLA). Although I did not previously point it out the quote from 6.5.3.4 above does say this.
Although in C11 as opposed to C99 it is unspecified whether sizeof is evaluated or not in this case.
Also, note there is a C++ version of this quesiton: Does not evaluating the expression to which sizeof is applied make it legal to dereference a null or invalid pointer inside sizeof in C++?.
The sizeof operator is a pure compile-time operation. Nothing is done runtime, which is why it works fine.
By the way, the path member is not actually a pointer, so it can't technically be NULL.
Stating that sizeof is a purely compile-time construct (as currently existing answers do) is not entirely accurate. Since C99, sizeof is not a purely compile time construct. The operand of sizeof is evaluated at run-time of the operand type is a VLA. The answers posted so far seem to ignore that possibility.
Your code is fine, since it does not involve any VLA. However, something like this can be a different story
unsigned n = 10;
int (*a)[n] = NULL; // `a` is a pointer to a VLA
unsigned i = 0;
sizeof a[i++]; // applying `sizeof` to a VLA
According to the C99 standard, the argument of sizeof is supposed to be evaluated (i.e. i is supposed to get incremented, see https://ideone.com/9Fv6xC). However, I'm not entirely sure that the null-point dereference in a[0] is supposed to produce undefined behavior here.

Why is the sizeof() a char array sometimes sizeof(void *) and sometimes sizeof(the array)? [duplicate]

This question already has answers here:
Length of array in function argument
(9 answers)
Closed 9 years ago.
#include<stdio.h>
void printS(char []);
int main(){
char str[]="The C Programming Language";
printf("%d \n",sizeof(str)); //output=27
printS(str);
}
void printS(char s[]){
printf("%d \n",sizeof(s)); //output=4
}
Why this anamolous output
please explain what is the difference between 'str' and 's'....
and how can i have sizeof() output=27 in printS function.
When you pass an array to a function like you are it will decay to a pointer and therefore sizeof will be returning the size of a pointer not the size of the array. The C Faq's section on Arrays and Pointers is a great reference and Question 6.4 covers this exact issue. The relevant section of the C99 draft standard is section 6.3.2.1 Lvalues, arrays, and function designators paragraph 3 which says(emphasis mine):
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
In order to obtain the length of a C style string you can use strlen from string.h header file.
The value of sizeof() is the size of one variable of the specified type. s is actually char*, so sizeof(s) is 4 (on your 32-bit platform). In main(), str is treated as an array of char, so sizeof(str) is the size of the array. Note that the length of "The C Programming Language" is 26, the extra one byte is for the zero terminator.
To get the length of s, use strlen(s). This time the zero terminator is not counted. And don't forget to #include <string.h> at the beginning.
C does not have the feature of passing array values. Arrays are always passed as pointers, when you declare a parameter of type foo[] you are effectively declaring foo *.

Why operator sizeof( function ) in C is outputting 1 byte [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is the size of a function in C always 1 byte?
Consider the below code snippet in C:
double fn()
{
return 1.1 ;
}
int main()
{
printf( "%d", sizeof( fn ) );
return 0;
}
The output is:
1
Why the sizeof() operator is outputting 1 byte?
The sizeof operator should not be applied to a function. It is meaningless and its behaviour is not defined.
The size operator shall not be applied to an expression that has
function or incomplete type,...
Reference: ISO/IEC 14882 (section 5.3.3)
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.
Reference: ISO/IEC 9899:1999 (section 6.5.3.4)
The sizeof operator may not be applied to:
A bit field
A function type
An undefined structure or class
An incomplete type (such as void)
Reference: http://publib.boulder.ibm.com/
When you use sizeof on a function, it's value is meaningless, as described here Why is the size of a function in C always 1 byte?
To get the size of the return value, try using sizeof(fn()), because sizeof is a compile-time constant (in most scenarios), fn will not really be called, however.
To get the size that the function takes up in bytes, however, is not possible to do portably, unfortunately. If you told us what you really wanted to accomplish, we could probably help you do more.

Resources