Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a[n] really interchangeable with *(a+n) - why does sizeof return two different answers?

Tags:

arrays

c

pointers

I'm having a problem understanding one thing in C. I've read in "ANSI C" that statements like a[n] where a is array are really equivalent to *(a+n). So here's a small code snippet I've written to check that:

#include <stdio.h>
int main(void)
{
    int a[10] = {0,1,2,3,4,5,6,7,8,9};
    int *p = a;
    printf("sizeof a: %d\n", sizeof(a));
    printf("sizeof p: %d\n", sizeof(p));
    return 0;
}

After executing the code the program outputs:

sizeof a: 40
sizeof p: 8

I don't understand - what did I just do? How are a and p different objects? (Judging by the output of sizeof function)

like image 883
qiubit Avatar asked Feb 11 '23 10:02

qiubit


2 Answers

According to 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.

So object a defined as an array of 10 integers occupies a memory extent that has size of 40 bytes because each element of it in turn has size of 4 bytes (that is in your environment sizeof( int ) is equal to 4).

int a[10] = {0,1,2,3,4,5,6,7,8,9};

Object p is defined as a pointer and initialized by the address of the first element of the array a

int *p = a;

In the environment where you compiled the program size of pointer is equal to 8 bytes.

You can consider declaration

int *p = a;

also like

int *p = &a[0];
like image 136
Vlad from Moscow Avatar answered Feb 12 '23 22:02

Vlad from Moscow


Yes, the expression a[n] is equivalent to *(a+n). But that's not relevant to your code sample.

You've defined a as an array object consisting of 10 int objects, and p as a pointer object of type int*. The equivalence you mention means, for example, that the expressions a[5] is equivalent to *(a+5; both are int expressions with the value 5. But neither expression appears in your code.

You've defined a and p as objects of different types, and there is no rule in C that says these objects are interchangable. sizeof a is equivalent to 10 * sizeof (int), and sizeof p is equivalent to sizeof (int*) (the size of a pointer to int).

One special rule that your program does depend on is that an expression of array type is, in most contexts, implicitly converted to a pointer to the array's initial element. In:

int *p = a;

a is an expression of array type. It's converted to the equivalent of &a[0], and that pointer value is used to initialize p. Thereafter, a and p are equivalent in most contexts; they both refer (one indirectly, one directly) to the address of the initial element of the array object a. But the operand of the sizeof operator is one of the contexts in which this conversions does not take place; sizeof a yields the size of the array object, not the size of a pointer.

All this is explained very well in section 6 of the comp.lang.c FAQ.

like image 20
Keith Thompson Avatar answered Feb 12 '23 22:02

Keith Thompson