Is dereferencing null pointer valid in sizeof operation [duplicate] - c

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.

Related

Why does C allow the sizeof operator on a variable that hasn't yet been created?

Consider the following example code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = malloc(sizeof *a);
*a = 5;
free(a);
return 0;
}
In this example, I allocate the integer a on the heap and initialize it to 5. This line specifically
int *a = malloc(sizeof *a);
is what is confusing me (the sizeof *a part). To me, this looks like I am trying to get the size of the variable before it is even created, but I see this style for initializing pointers is extremely common. When I compile this code with clang, I don't get any errors or warnings. Why does the compiler allow this? As far as I can tell, this is akin to doing something like
int a = a + 1;
without any previous declaration of a. This produces a warning with clang -Wall main.c:
main.c:17:13: warning: variable 'a' is uninitialized when used
within its own initialization [-Wuninitialized]
int a = a + 1;
What makes this line different from the pointer declaration with sizeof?
The operand of the sizeof operator is not evaluated unless it is a variable length array. It is only looked at to determine its type.
This behavior is documented in section 6.5.3.4p2 of the C standard:
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.
In this case, it knows that *a has type int, so *a is not evaluated and sizeof *a is the same as sizeof(int).
For most cases sizeof is a compile-time operator. The compiler simply knows the size of the type you pass to it.
Secondly, actually at the time malloc is called the variable a actually have been defined. The variable must have been defined (and allocated) before it can be initialized. Otherwise, where would the initialization value be written?
The problem with
int a = a + 1;
isn't that a doesn't exist, it's that the value of a is indeterminate when you use it in a + 1.
For some types an indeterminate value could contain a trap representation, and if that happens it leads to undefined behavior.
A small note about the sizeof operator: The only time it's not evaluated by the compiler itself at compile-time is for variable-length arrays.

C assignment expression in argument to sizeof [duplicate]

Here is the code compiled in dev c++ windows:
#include <stdio.h>
int main() {
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
I expect x to be 6 after executing note 1. However, the output is:
4 and 5
Can anyone explain why x does not increment after note 1?
From the C99 Standard (the emphasis is mine)
6.5.3.4/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.
sizeof is a compile-time operator, so at the time of compilation sizeof and its operand get replaced by the result value. The operand is not evaluated (except when it is a variable length array) at all; only the type of the result matters.
short func(short x) { // this function never gets called !!
printf("%d", x); // this print never happens
return x;
}
int main() {
printf("%d", sizeof(func(3))); // all that matters to sizeof is the
// return type of the function.
return 0;
}
Output:
2
as short occupies 2 bytes on my machine.
Changing the return type of the function to double:
double func(short x) {
// rest all same
will give 8 as output.
sizeof(foo) tries really hard to discover the size of an expression at compile time:
6.5.3.4:
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.
In short: variable length arrays, run at runtime. (Note: Variable Length Arrays are a specific feature -- not arrays allocated with malloc(3).) Otherwise, only the type of the expression is computed, and that at compile time.
sizeof is a compile-time builtin operator and is not a function. This becomes very clear in the cases you can use it without the parenthesis:
(sizeof x) //this also works
Note
This answer was merged from a duplicate, which explains the late date.
Original
Except for variable length arrays sizeof does not evaluate its arguments. We can see this from the draft C99 standard section 6.5.3.4 The sizeof operator paragraph 2 which says:
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.
A comment(now removed) asked whether something like this would evaluate at run-time:
sizeof( char[x++] ) ;
and indeed it would, something like this would also work (See them both live):
sizeof( char[func()] ) ;
since they are both variable length arrays. Although, I don't see much practical use in either one.
Note, variable length arrays are covered in the draft C99 standard section 6.7.5.2 Array declarators paragraph 4:
[...] If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.
Update
In C11 the answer changes for the VLA case, in certain cases it is unspecified whether the size expression is evaluated or not. From section 6.7.6.2 Array declarators which says:
[...]Where a size expression is part of the operand of a sizeof
operator and changing the value of the size expression would not
affect the result of the operator, it is unspecified whether or not
the size expression is evaluated.
For example in a case like this (see it live):
sizeof( int (*)[x++] )
As the operand of sizeof operator is not evaluated, you can do this:
int f(); //no definition, which means we cannot call it
int main(void) {
printf("%d", sizeof(f()) ); //no linker error
return 0;
}
Online demo : http://ideone.com/S8e2Y
That is, you don't need define the function f if it is used in sizeof only. This technique is mostly used in C++ template metaprogramming, as even in C++, the operand of sizeof is not evaluated.
Why does this work? It works because the sizeof operator doesn't operate on value, instead it operates on type of the expression. So when you write sizeof(f()), it operates on the type of the expression f(), and which is nothing but the return type of the function f. The return type is always same, no matter what value the function would return if it actually executes.
In C++, you can even this:
struct A
{
A(); //no definition, which means we cannot create instance!
int f(); //no definition, which means we cannot call it
};
int main() {
std::cout << sizeof(A().f())<< std::endl;
return 0;
}
Yet it looks like, in sizeof, I'm first creating an instance of A, by writing A(), and then calling the function f on the instance, by writing A().f(), but no such thing happens.
Demo : http://ideone.com/egPMi
Here is another topic which explains some other interesting properties of sizeof:
sizeof taking two arguments
The execution cannot happen during compilation. So ++i/i++ will not happen. Also sizeof(foo()) will not execute the function but return correct type.
sizeof runs at compile-time, but x++ can only be evaluated at run-time. To solve this, the C++ standard dictates that the operand of sizeof is not evaluated. The C Standard says:
If the type of the operand [of sizeof] is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
This line here:
printf("%d and ", sizeof(x++)); // note 1
causes UB. %d Expects the type int not size_t. After you get UB the behavior is undefined including the bytes written to stdout.
If you would fix that by replacing %d with %zu or casting the value to int, but not both, you would still not increase x but that is a different problem and should be asked in a different question.
sizeof() operator gives size of the data-type only, it does not evaluate inner elements.

Why can this C code run correctly? [duplicate]

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).

Using Increment operator with de-referencing in C

To my function i get a void pointer, I would like to point to the next location considering the incoming pointer is of char type.
int doSomething( void * somePtr )
{
((char*)somePtr)++; // Gives Compilation error
}
I get the following compilation error:
Error[Pe137]: expression must be a modifiable lvalue
Is this an issue with the priority of operators?
A cast does not yield an lvalue (see section 6.5.4 footnote 104 of C11 standard), therefore you can't apply post increment ++ operator to its result.
c-faq: 4.5:
In C, a cast operator does not mean "pretend these bits have a different type, and treat them accordingly"; it is a conversion operator, and by definition it yields an rvalue, which cannot be assigned to, or incremented with ++. (It is either an accident or a deliberate but nonstandard extension if a particular compiler accepts expressions such as the above.)
Try this instead
char *charPtr = ((char*)somePtr);
charPtr++;
If you want to move the pointer to next then you can use:
*ptr++;
If you want to Change copy the pointer position to another variable then:
char *abc = (char*)(def + 1);
It really depends on your motive to do things

sizeof- function or macro? [duplicate]

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:

Resources