#include <stdio.h>
int main() {
int(*ptr)[5];
printf("%zu\n", sizeof ptr); // size of a pointer - expression sizeof
printf("%zu\n", sizeof(void*)); // size of a pointer - type sizeof
printf("%zu\n", sizeof *ptr); // size of an int[5] - expression sizeof
printf("%zu\n", sizeof(int[5])); // size of an int[5] - type sizeof
}
7条答案
按热度按时间mmvthczy1#
我使用的是64位系统。当我在gcc编译器中运行这段代码时,它会生成输出8和20。我的问题是要为这个点分配多少字节到一个数组中?是8还是20,为什么?
首先要考虑的是
ptr
是static
。除了代码生成中明显的一个之外,没有任何分配:在64位机器中,8个字节用于指针。ptr
是指针,并指向一个大小为5int
的区域。编译器会告诉你ptr
是int(*)[5]
。它只是一个指向一个4-byteint
machine.并不指向任何东西。所以问题的标题不是我们在代码中所拥有的:没有内存分配。
在这里的代码是不多看:
字符串
但考虑
型
示出
型
也许事情变得更清晰了:
ptr = x;
使ptr
指向数组x
ptr = message;
使ptr
指向char[]
数组。(*ptr)[4] = 0x00636261;
将字符串的最后4个字节更改为“abc”。所有这些都是声明
ptr
为int (*ptr)[5]
时括号的效果。本守则所
型
我们没有括号,
型
我们看到了正常的东西:一个指向
int
的5个指针的数组,等等。c3frrgcw2#
我的问题是要为这个点分配多少个字节到一个数组?是8个还是20个,为什么?
这取决于你是需要为指针分配内存还是为它所指向的内存分配内存。
你需要知道你正在看的东西的大小:
字符串
备注:
%lu
不是正确的转换。请将%zu
用于sizeof
。uubf1zoe3#
你声明
ptr
是一个指向5个整数的数组的指针。ptr
保存的地址是8个整数。当你用
*ptr
查找地址(解引用)时,你会得到一个5个整数的数组,它是5*sizeof(int) = 5*4 = 20
注意:
ptr
中可能有一个地址,但该地址没有分配内存。为此,您需要调用
ptr = malloc(sizeof(*ptr))
如果不这样做,对数组的访问将发生故障。例如
*ptr[0]=0;
waxmsbnn4#
ptr
指定一个对象,它将存储int
的5元素数组的 * 地址 *。在您的系统上,这样的指针占用8个字节的存储空间。*ptr
可以指定一个int
的5元素数组对象;在您的系统上,这样的数组占用20个字节(5个4字节元素)。假设代码:
字符串
这给了你类似下面的东西(每个盒子占用4个字节):
型
这相当于写
型
指针的大小并不取决于它所指向的对象的大小。
hivapdat5#
我的问题是要为这个点分配多少个字节到一个数组?是8个还是20个,为什么?
你不为指向数组或其他对象的指针分配内存。你为数组或其他对象分配内存。指针只是用来指向它。它与内存没有任何内在的关联。
要为数组或其他对象分配内存,您可以告诉
malloc
您需要为该对象分配多少字节。例如,void *p = malloc(12);
为C中使用12字节或更少的任何对象分配内存,只要它没有扩展对齐要求。(C中的所有基本对象,标准的整数、指针和浮点类型,以及由它们组成的数组、联合和结构,都有malloc
满足的 * 基本 * 对齐要求。sizeof
运算符将帮助您确定需要多少字节。您可以给予sizeof
运算符一个类型,例如对于5个int
的数组,int [5]
,它将给予正确的字节数:字符串
注意
p
的类型与分配的内存或放入的内存无关。指针只是一个指针。然而,你可以声明一个适当类型的指针,并将其与
sizeof
一起使用。给定int *p;
,则如下代码:型
表示为
p
指向的任何类型的对象分配足够的内存。注意,必须使用sizeof *p
来表示p
指向的大小,而不是sizeof p
,因为sizeof p
是指针p
的大小,而不是p
指向的类型的大小。如果
p
要指向一个对象数组的第一个对象,你可以通过相乘来得到数组的大小:型
你也可以使用一个指向整个数组的指针,而不是一个元素,像这样:
型
没有明确乘以元素的数量,因为
*p
代表整个数组,而不是其中的单个元素。然而,这种形式并不经常使用,因为使用p
访问数组的元素会更困难。由于*p
是整个数组,而不是第一个元素,你需要使用(*p)[i]
来访问元素i
。当p
只是指向第一个元素的指针时,你可以使用p[i]
来访问一个元素。因此,声明这样一个指针为
int *p
比int (*p)[5]
更受欢迎,除非有额外的情况需要引用整个数组。q1qsirdb6#
在你的代码中,
int (*ptr)[5]
;声明了一个指向5个整数的数组的指针。让我们分解一下大小计算:sizeof(ptr)
:这给出了指针本身的大小。在64位系统上,指针通常占用8个字节。因此,sizeof(ptr)
将是8。sizeof(*ptr)
:这给出了ptr指向的对象的大小,它是一个5个整数的数组(int[5]
)。数组的大小是一个元素的大小乘以元素的数量。在这种情况下,sizeof(int)
在大多数系统上通常是4个字节,而你有5个元素。因此,sizeof(*ptr)
将是4 * 5 = 20。因此,您看到的输出(
sizeof(ptr)
为8,sizeof(*ptr)
为20)是正确的。这意味着指针本身占用8个字节,它指向的数组(5个整数的数组)占用20个字节。mutmk8jj7#
sizeof
运算符可以应用于完整的对象类型。声明了一个指向
int[5]
类型数组的指针。字符串
printf
的调用型
返回指针的大小。注意指针总是完整类型。
*ptr
具有完整的数组类型int[5]
。型
生成一个5个元素的数组,元素类型为
int
。运算符
sizeof
产生一个类型为size_t
的值。所以你应该重写上面对printf
的调用,例如:型
使用转换说明符
zu
而不是lu
,因为类型size_t
不一定是类型unsigned long
的别名。C标准允许size_t
作为类型unsigned long long
的别名,尽管在大多数系统中它确实是类型unsigned long
的别名你可以声明一个指向不完整数组类型的指针,
型
正如上面指出的,在任何情况下,指针都是一个完整的类型。
型
现在,由于这种情况下的数组类型是不完整的,因此对于此语句,
型
编译器将发出错误。
如果一个数组不是可变长度数组,那么它的大小在编译时确定。
你可以声明一个指向可变长度数组的指针。
型
在这种情况下,输出指针大小的
printf
的调用将打印相同的值。指针的值不会改变,尽管指针指向的数组类型在for循环的每次迭代中都会改变,并且如果变量i
并在运行时求值,则输出的数组大小将取决于当前值。时间。尝试自己的演示程序。请记住,数组的大小计算为数组中元素的数量乘以其元素的大小(元素类型的大小)。