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