我是 C 语言的初学者。不过,当动态分配数组时,为什么类型通常保留为指向动态分配的内存块中第一个元素的指针?相反,是否可以将其分配给(指向)长度等于分配的数组类型?
我制作了一个示例程序,它显示了仅使用指向数组第一个元素的指针的“传统”版本以及将其分配给(指向)数组的“数组”版本。
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 10
int main() {
// Option 1: Pointer to type (first element)
// Create pointer to int for the dynamically allocated array
// Size information stored in ARR_SIZE
int *arr_ptr = malloc(sizeof(int) * ARR_SIZE);
// Do something to each element
printf("Option 1: int pointer\n");
for(size_t i = 0; i < ARR_SIZE; i++) {
printf("i: %zu\n", i);
arr_ptr[i] = i;
}
// Option 2: Assign to (a pointer to) an array type
// Since we assign it to (a pointer to) an array type of correct size, we embed the size information into the type
int (*arr_ptr2)[ARR_SIZE] = malloc(sizeof(int) * ARR_SIZE);
// Do something to each element
printf("Option 2: assign to array pointer\n");
// No longer need to use ARR_SIZE as the size information is stored in the array type
for(size_t i = 0; i < sizeof(*arr_ptr2)/sizeof(int); i++) {
printf("i: %zu\n", i);
(*arr_ptr2)[i] = i;
}
// Print some size information
printf("Size of int: %zu\n", sizeof(int)); // Prints 4
printf("Size of *arr_ptr: %zu\n", sizeof(*arr_ptr)); // Prints 4
printf("Size of *arr_ptr2: %zu\n", sizeof(*arr_ptr2)); // Prints 40
// Free memory ...
return 0;
}
这个例子表明,分配给(指向)数组类型意味着数组的长度“嵌入”在类型本身中,因此可以从变量本身获取分配的内存块的大小,而不需要“大小变量”。虽然这可能不是分配给数组类型的好处的最佳示例,但我想还有其他好处,例如清楚地表明该变量是元素数组而不是指向单个元素的指针。
将其分配给这样的数组类型有什么缺点吗?或者仅仅使用指针的好处是否超过了潜在的好处?例如,由于数组无论如何都会衰减为指针,这是否会成为一个无用的麻烦的“额外步骤”?
感谢您提供的任何见解和澄清!
...当动态分配数组时,为什么类型通常保留为指向动态分配的内存块中第一个元素的指针?
记号更容易。如果
p
的类型是指向元素的指针,则 p[i]
是元素 i
。如果类型是指向数组的指针,则 (*p)[i]
是元素 i
。早期的 C 被设计得简洁。
C 的早期开发旨在在许多情况下使用指针代替数组。早期的 C 主要处理标量对象,并且使用带有数组索引的指针 (
p[i]
) 提供了一种访问数组元素的简单方法,而无需向语言添加对更复杂类型和表达式的支持。
我们经常希望使用动态分配的内存,其大小在运行时确定,例如从输入或文件读取的字符串。使用指向编译时类型未知的数组的指针将要求该数组具有可变长度类型或不完整类型。早期 C 中不存在可变长度类型,而且我不认为不完整类型(如果存在的话)得到了很好的定义。 (“不完整”在 Kernighan 和 Ritchie 第二版的索引中,但在第一版中没有。)