指针数组的大小。

3

i have a doubt regarding sizeof operator

Code 1:

int main()
{
    int p[10];
    printf("%d",sizeof(p));   //output -- 40
    return 0;
}

代码 2:

int main()
{
    int *p[10];
    printf("%d",sizeof(*p));   //output -- 4
    return 0;
}

在第一段代码中,p指向一个整数数组。在第二段代码中,p指向一个指针数组。我不理解为什么第一段代码的输出是40,而第二段代码的输出是4,即使它们都指向了同样大小的数组?


2
在您的第二个示例中(通常适用于数组),*pp[0] 相同。因此,sizeof(*p)sizeof(p[0]) 相同,都是指针的大小。 - pmg
6个回答

9
以下程序的输出将为您提供有关类型大小和类型指针的一些提示和理解。
#include <stdio.h>

int main(void)
{
    int p1[10];
    int *p2[10];
    int (*p3)[10];

    printf("sizeof(int)   = %d\n", (int)sizeof(int));
    printf("sizeof(int *) = %d\n", (int)sizeof(int *));
    printf("sizeof(p1)    = %d\n", (int)sizeof(p1));
    printf("sizeof(p2)    = %d\n", (int)sizeof(p2));
    printf("sizeof(p3)    = %d\n", (int)sizeof(p3));

    return 0;
}

int p[10];      => 10 consecutive memory blocks (each can store data of type int) are allocated and named as p

int *p[10];     => 10 consecutive memory blocks (each can store data of type int *) are allocated and named as p

int (*p)[10];   => p is a pointer to an array of 10 consecutive memory blocks (each can store data of type int) 

现在来回答您的问题:
>> in the first code p points to an array of ints.
>> in the second code p points to an array of pointers.

您说得很对。在代码2中,为了获取p指向的数组的大小,需要传递基地址。

printf("%d", (int)sizeof(p));

而不是以下内容

printf("%d", (int)sizeof(*p));   //output -- 4

以下表达式是等价的:
*p, *(p+0), *(0+p), p[0]

>> what's the difference between p[10] and 
>> (*p)[10]...they appear same to me...plz explain

以下是对您其他问题的回答:
int p[10];
 _________________________________________
|   0   |   1   |   2   |         |   9   |
| (int) | (int) | (int) |  ...    | (int) |
|_______|_______|_______|_________|_______|


int (*p)[10]
 _____________________
|                     |
| pointer to array of |
|     10 integers     |
|_____________________|

p[10]和(*p)[10]有什么区别?它们在我看来是一样的,请解释一下。 - Amol Sharma
我已经更新了我的先前回答,以包含您上述提出的问题。希望这可以帮到您。 - Sangeeth Saravanaraj
谢谢,我明白了。在p[10]的情况下,您无法修改p,但可以在(*p)[10]的情况下进行修改,例如增量操作。 - Amol Sharma
@AmolSharma 我很高兴。另一方面,你能否在完成练习/学习后将正确的帖子标记为回答你的问题? - Sangeeth Saravanaraj

5
基本上,您有一个指针数组。当您执行*p时,您取消引用指向数组第一个元素的指针。因此,类型将为int。 sizeof(int *)在您的机器上恰好为4。
编辑(澄清):
代码片段1中,您正在获取数组的大小。
代码片段2中,您正在获取指向指针数组第一个元素的类型的大小。

1
OP解引用了指针。sizeof(*p)表示“指针所指向的对象的大小”。 - tangrs
*p不是被解引用的对象,sizeof获取的是该对象的大小吗?我从未听说过sizeof不接受解引用参数。 - tangrs
等等,p 将会衰变成“指向指针的指针”,对其进行解引用将得到“指向整数的指针”。那么,r_ahlskog 在他的机器上是如何得到结果的呢?现在我有点困惑了 o_O - tangrs
哦,那真是一个狡猾的错误。当你不确定时,请编写一个测试用例。我没有注意到p被声明为不同类型。请参考http://ideone.com/34hH3获取参考代码。然而,该机器似乎是32位的。 - r_ahlskog
@cnicutar 当然定义了 sizeof(*p)。在这种情况下,它是 sizeof(int*) - Firoze Lafeer
显示剩余6条评论

4
在第一个代码中:
int p[10];

p并不指向一个整型数组;实际上,p就是一个整型数组。在这个语句中:

printf("%d",sizeof(p));

应该是什么?
printf("%d", (int)sizeof(p));

表达式p仍然引用数组对象,因此sizeof(p)返回数组对象的大小,在您的系统上为40字节(10 * sizeof (int))。

在第二个示例中:

int *p[10];

再次强调,p是一个指针数组。但在下面的语句中:

printf("%d", (int)sizeof(*p));

表达式p会被转换为数组的第一个元素的指针(而不是整个数组)。用一元运算符*去解引用该指针可以得到一个int*对象,即数组的第一个元素。在您的系统上int*指针的大小恰好为4。(sizeof (int)sizeof (int*)不一定相同;在您的系统上它们的大小是相等的。)
在C语言中,规则是任何数组类型的表达式(例如数组变量的名称)都会自动转换为指向数组的第一个元素的指针--大多数情况下都是如此。但是有三个例外:
  • 当它是sizeof的操作数(sizeof arr给出的是数组对象的大小,而不是指针的大小)
  • 当它是一元运算符&的操作数(&arr会给出整个数组对象的地址,而不是它的第一个元素的地址;它们位于相同的内存位置,但是类型不同)
  • 当它是初始化数组对象时使用的字符串字面值(int arr[6] = "hello";不会将"hello"转换为指针,而是复制了该数组)。
强烈推荐阅读: comp.lang.c FAQ的第6节。

2
在第一段代码中,sizeof(Array)将会返回为该数组分配的总字节数。您可以通过此方法来获取正确的数组大小:
int size= sizeof(Array)/sizeof(Array[0]);

在第二个代码中,它返回指针的大小。

2

请检查这段代码:

在这段代码中,p指向一个指针数组,因此输出结果为40。

在您的情况下,它是一个指针数组,因此输出结果为4。

#include<stdio.h>
int main()
{
       int (*p)[10];
       printf("%d",sizeof(*p));   //output -- 40
       return 0;
}

0

看一下你的第一个代码片段,p是一个大小为40字节的数组。现在它如何变成40字节很简单,数组p包含10个成员,每个成员的大小为4字节。

   10*4=40

在第二段代码片段中,p代表的是指针数组,也就是说,该数组的每个成员都是一个指向int值的指针。现在,*p表示数组的第一个下标处的值,而这个值实际上是一个地址,长度为4个字节。
希望现在对您来说一切都清楚了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接