开发者

Given `int num[7]`, how do `num` , `&num[0]`, `&num` differ?

I read in a C book that for an array num[7] the term num is equivalent to &num[0]. This concept was working fine for me but when I wrote this program shown below I again got confused.

#include<stdio.h>
#include<conio.h>
int main()
{
    int num[]={21,22,23,24,25,26,27};
    int *x,*y,*z;
    x=&num;
    y=num;
    z=&num[0];
    printf("%d   %d   %d\n",sizeof(x),sizeof(y),sizeof(z));
    printf("%d  %d  %d\n",sizeof(&num),sizeof(num),sizeof(&num[0]));
    printf("%d   %d   %d",*(&num),*(num),*(&num[0]));
    getch();
    return 0;  
}

output is:

      4    4    4
      4    28   4
      2293536   21   21

If num is identical to &num[0] then why there is a difference in their size? And what is this third type of term &num? I know it is showing a garbage value but does this type of term makes any sense? z=&num[0] I already understand. The compiler shows a warning for the assignment x=&num, but for y=num; the compiler doesn't have any problems. If num has size 28 then why did it get assigned to an integer pointer y without a typecast开发者_开发问答?

Then I tried on 2-d array this way:

#include<stdio.h>
#include<conio.h>
int main ()
{
    int s[4][2]={{1234,56},{1235,57},{1236,58},{1237,59}};
    int i
    printf ("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s),
        sizeof(s[0][0]),sizeof(&s));
    getch();
    return 0;
}

Now the output is

8  4  32  4   4

Here sizeof(s[i]) is 8. because s[i] is a 1-D array and it has two elements so it's fine. But I don't have any clue what the terms &s[i] and &s mean. And I am again able to see that s is not identical to s[0][0] . I have used Dev C++ 4.9.9.2 version to run all the programs. I want to be clear in these three type of terms.


Good questions here. Hopefully we can all explain these issues for you.

Given

int num[]={21,22,23,24,25,26,27};

Then

  • num has type int[] because it is a declared array of integers whose memory is allocated in place. Note that it does not have the type int*, which would have been the case if you malloced it.
  • sizeof(num) is 28 because num is an array of 7 ints, which on your machine are 4 bytes in size. The value would be 56 if ints were 8 bytes or 14 if they had 2 bytes, but 4 bytes per integer is most common.
  • &num[0] is a pointer, of type int*, whose value is the address of the first element of num.
  • The sizes of x and friends are 4 because they are declared as pointers, which on your machine, under your C compiler, pointers are allocated in 4 bytes.

The thing to keep in mind is that when an array is used in certain contexts, like being passed as a parameter, it is converted to an int*. That is why you can say *num and get 21. Tricky, but that's how it is. That is why one can usually interchange num and &num[0] but you really should keep the distinction in mind, because as you noticed, the sizeof values differed.

The conversion is why y = num makes sense. y has type int* and in C you get an automatic conversion from int[] TO int*. You can't do x = &num because the type of &num is "pointer to int array." You cannot assign that to an int* (pointer to int).

In the case of

int s[4][2]={{1234,56},{1235,57},{1236,58},{1237,59}};

We have the type of s as int[][], the type of &s as pointer to int[][] and the type of &s[i] as pointer to int[] (because s[i] is an int array). Because of the way C allows you assign/pass arrays to pointers you can play the same kind of games as in your first example.

You will notice that s, &s[0] and &s[0][0] all point to the same memory locations, but, as you noticed, the sizeof values will be different.


Your contradictions are valid. It is not the case that num is equivalent to &num[0]. That's simply false. Arrays are a distinct type from pointers, and num refers to an object with the type int[7], not int*. That's why the size is different, for example, because one is a contiguous collection of seven integers.

Note that if the need be, num may be converted to an int*, with the value &num[0]. A conversion is not the same as equivalence, of course. You'll find this confusion between arrays and pointers oddly prominent, because people keep repeating the falsity that arrays are pointers. They aren't.


Now my question is if num is identical to &num[0] then why there is a difference in there size?

num is an array. sizeof has a sometimes surprising behavior for arrays which is that it tells you the storage size of the whole array if you pass it an actual array, but it only tells you the size of a pointer to an element in the array if you pass it the address of such an element. This can lead to confusion because the array name degrades to a pointer in function calls.

So, the answer is that num is not identical to &num[0] - the latter is the address of the first element of num, with any information about the total size of the array removed. These two things are interchangeable in many contexts, such as calling actual functions, but not when calling sizeof (which is not a function, but a special keyword handled by the compiler).


Wow, that's a lot of questions in one go :P

First I'll try to explain this output to you:

  4    4    4
  4    28   4
  2293536   21   21

sizeof() is a unary operator in c. It is replaced by an integer when the code is compiled, not at runtime. So the compiler literately changes your printfs to:

 printf("%d   %d   %d\n", 4, 4, 4);
 printf("%d  %d  %d\n", 4, 28, 4);
 printf("%d   %d   %d",*(&num),*(num),*(&num[0]));

In a very early stage in the compilation.

The compiler is kind enough to give you the size of the entire array when you write sizeof(num). That's how sizeof is defined to work on arrays. All the other elements give you the size of an (int *) except sizeof (&num) which gives you the size of an (int **) (an int ** is the same size as an int * anyways).

  • &num is the memory location of the pointer to your array
  • num, and &num[0], is the memory location of the first int in your array

For your second question;

printf("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s),sizeof(s[0][0]),sizeof(&s));

 

sizeof(s[i]) - size of an array (int[2]) == 8
sizeof(&s[i]) - size of a pointer to an int array sizeof(int **) == 4
sizeof(s) - size of a 2D array containing 8 ints == sizeof(int[8]) == 32
sizeof(s[0][0]) - size of an int === 4
sizeof(&s) - size of a pointer to an array == 4
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜