2

Please explain the OP for below code snippet :

int *a="";
char *b=NULL;
float *c='\0' ; 
printf(" %d",sizeof(a[1])); // prints 4 
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4

Compiler interprets a[1] as *(a+1) , so a has some address , now it steps 4 bytes ahead , then it will have some garbage value there so how is the OP 4 bytes , even if I do a[0] , still it prints 4 , although it is an empty string , so how come its size is 4 bytes ?

Here we are finding out the size of the variable the pointer is pointing to , so if I say size of a[1] , it means size of *(a+1), Now a has the address of a string constant which is an empty string , after I do +1 to that address it moves 4 bytes ahead , now its at some new address , now how do we know the size of this value , it can be an integer , a character or a float , anything , so how to reach to a conclusion for this ?

9
  • 2
    What compiler are you using that lets any of that compile? Commented Mar 24, 2017 at 15:37
  • @Mysticial Any c compiler? ideone.com/p9PyKX Commented Mar 24, 2017 at 15:38
  • 2
    The sizeof operator works actually on type not on the value of an expression. Thus, it returns the correct result without even access the value (which otherwise might have caused a crash). Commented Mar 24, 2017 at 15:39
  • I am using GCC-4.9.2 Commented Mar 24, 2017 at 15:40
  • 1
    @Scheff Not totally true, there's variable-length arrays too. Those have to have sizeof evaluate at runtime. Commented Mar 24, 2017 at 15:45

4 Answers 4

4

The sizeof operator does not evaluate its operand except one case.

From the C Standard (6.5.3.4 The sizeof and alignof operators)

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.

In this code snippet

int *a="";
char *b=NULL;
float *c='\0' ; 
printf(" %d",sizeof(a[1])); // prints 4 
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4

the type of the expression a[1] is int, the type of the expression b[1] is char and the type of the expression c[1] is float.

So the printf calls output correspondingly 4, 1, 4.

However the format specifiers in the calls are specified incorrectly. Instead of "%d" there must be "%zu" because the type of the value returned by the sizeof operator is size_t.

From the same section of the C Standard

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

Sign up to request clarification or add additional context in comments.

7 Comments

I found sizeof in cppreference.com which states return type size_t (would have been my first guess also). Interesting that the cited standard says: The result is an integer. Is the actual "return type of sizeof" mentioned somewhere else?
@Scheff See my appended post.
@Scheff You are a kind person.:)
@stackuser You declared three pointers. The expression with the subscript operator applied to a pointer has the pointed type. Thus for example if you write int *a; then the expression a[1] has type int. As I wrote in the answer expressions in the sizeof operator are not evaluated except when the operand is a variable length array and are known at compile time. Outside the sizeof operator the expressions you are using are invalid and have undefined behavior.
@stackuser You are right. The compiler just determines the type of the expression.
|
3

This is all done statically, i.e. no dereferencing is happening at runtime. This is how the sizeof operator works, unless you use variable-length arrays (VLAs), then it must do work at runtime.

Which is why you can get away with sizeof:ing through a NULL pointer, and other things.

You should still be getting trouble for

int *a = "";

which makes no sense. I really dislike the c initializer too, but at least that makes sense.

3 Comments

Makes no sense to humans, but to the computer a char to float* is implicit and makes plenty of sense.
@FantasticMrFox it's a pointer to float, so what really happens is float * c = '\0' == 0 => NULL; though it's a confusing way to assign a NULL.
@Kninnug Yeah, I was over-reacting a bit regarding c, changed.
2

sizeof operator happens at compilation (except for VLA's). It is looking at the type of an expression, not the actual data so even something like this will work:

sizeof(((float *)NULL)[1])

and give you the size of a float. Which on your system is 4 bytes.

Live example

Even though this looks super bad, it is all well defined, since no dereference ever actually occurs. This is all operations on type information at compile time.

1 Comment

Not totally true, there are variable-length arrays.
1

sizeof() is based on the data type, so whilst it's getting the sizes outside the bounds of memory allocated to your variables, it doesn't matter as it's worked out at compile time rather than run time.

1 Comment

It's not a function, the parentheses are not part of the operator's name.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.