这里考虑以下代码示例:
int *a = malloc(sizeof(int) * n);
这段代码可以用来定义一个包含n个整数的数组吗?
答案 0 :(得分:7)
int *a = malloc(sizeof(int) * n);
这段代码可以用来定义一个包含n个整数的数组吗?
这取决于“定义数组”的含义。
声明如下:
int arr[10];
定义一个命名数组对象。您的指针声明和初始化没有。
然而,malloc
调用(如果成功并返回非NULL
结果,如果 n > 0
)将在运行时创建一个匿名数组对象。
但它没有“定义数组a
”。 a
是指针对象的名称。鉴于malloc
调用成功,a
将指向数组对象的初始元素,但它本身不是数组。
请注意,由于数组对象是匿名的,因此没有任何内容可以应用sizeof
,也无法从指针中检索数组对象的大小。如果您需要知道阵列的大小,您需要自己跟踪它。
(有些评论表明malloc
调用会分配可以容纳n
整数对象但不包含数组的内存。如果是这种情况,那么您将无法访问创建的数组对象的元素。有关指针添加的定义,请参阅N1570 6.5.6p8;有关malloc
调用如何创建可访问数组的说明,请参阅7.22.3p1。)
答案 1 :(得分:4)
int *a = malloc(sizeof(int) * n);
假设malloc()
调用成功,您可以使用数组表示法(例如a
)使用指针a[0] = 5;
,如数组。但是a
本身并不是一个数组;它只是一个指向int
的指针(它可能是一个可以存储多个int
s的内存块。)
您的评论
但是我可以在我的程序中使用数组a,否则没有声明
表明这是你主要询问的内容。
用C语言编写
p[i] == *(p + i) == *(i + p) == i[p]
只要i
或p
中的一个是指针类型(p
也可以是一个数组 - 因为它将被转换为任何表达式中的指针)。因此,您可以像访问数组一样索引a
。但是a
实际上是一个指针。
答案 2 :(得分:3)
非常字面地解释你的问题,答案是否定的:“定义数组”意味着非常具体的东西;数组定义类似于:
int a[10];
您发布的内容是内存分配。它分配一个适合保存10 int
个值的数组的空间,并存储指向该空间中第一个元素的指针 - 但它不定义数组;它分配一个。
话虽如此,您可以在任何一种情况下使用数组元素访问运算符[]
。例如,以下代码段是合法的:
int a[10];
for (int i = 0; i < 10; i++) a[i] = 0;
和
int *a = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) a[i] = 0;
然而,他们所做的事情之间存在细微差别。第一个定义一个数组,并将其所有元素设置为0.第二个分配存储,该存储可以保存等效类型的数组值,并通过将每个元素初始化为0来将其用于此目的。
值得指出的是,第二个例子没有检查分配错误,这通常被认为是不好的做法。此外,如果以后不释放分配的存储空间,它将构成潜在的内存泄漏。
答案 3 :(得分:3)
是。这正是malloc()
所做的。
重要的区别在于
int array[10];
将array
声明为一个数组对象,有足够的空间容纳10个整数。相反,以下内容:
int *pointer;
将pointer
声明为单个指针对象。
重要的是distiguinsh其中一个是指针而另一个是实际数组,并且数组和指针是密切相关的但是是不同的东西。但是,说下面没有数组也是错误的:
pointer = malloc(sizeof (int) * 10);
因为这段代码所做的正是为了分配一个具有10个整数空间的数组对象。指针pointer
包含该数组的第一个元素的地址。(C99草案,第7.20.3节“内存管理函数”)
答案 4 :(得分:0)
使用标准所写的语言来描述(不同于它的书呆子字面量所描述的语言),目的是malloc(n)返回一个指针,如果将其转换为a T*
可以被视为指向T[n/sizeof T*]
的第一个元素的指针。根据N1570 7.22.3:
如果分配成功,则返回的指针将适当对齐,以便可以将其分配给 指向具有基本对齐要求的任何类型的对象的指针,然后使用 在分配的空间中访问此类对象或此类对象的数组(直到该空间) 已明确释放)。
但是,指针加法和减法的定义不是说对“适当对齐”以允许访问对象数组的指针起作用,而是说到指向实际数组对象元素的指针。如果程序访问了20个int
对象的空间,我认为标准并没有说得出的指针在所有方面都表现得像是指向{{1}的元素[0]的指针一样},与例如指向int[20]
的元素[0] [0]的指针。当然,一个实现必须非常笨拙,不允许它同时使用,但是我认为标准实际上并不需要这种处理。