然后你需要把转换从(int**)改为(struct myStruct**),同样的,把参数改为sizeof。在sizeof的参数中使用*<myVar>意味着,如果变量的类型发生了变化,维护工作会减少。 最后是no need to cast the return from malloc。上述优点之一是,如果m的类型发生变化,则会导致不必要的维护。最后,我们只剩下:
for (int i=0; i<10; i++)
{
m[i] = malloc(10 * sizeof(*(m[i])));
// check if m[i] is NULL, handle that error as you want
// assuming not NULL, m[i] now points to enough space for 10 ints
}
5条答案
按热度按时间qoefvg9y1#
你已经分配了100个int,这将给予你一个指向
int
的指针。你不能用这种方式来下标。你的C编译器应该已经给你这个错误了。如果你想动态分配一个“二维”int数组,你需要显式地这样做,分配一个10个int指针的数组,然后为每个指针分配一个动态分配的10个int数组。
malloc
结果没有错误检查。*但是在这种情况下没有理由不在堆栈上分配。由于它是在
main
中声明的,因此当将指向它的指针传递给其他函数时,将不会出现生存期问题,并且在堆栈上分配的数据量也不会太大。kse8i1jr2#
根据
[]
下标运算符的定义,表达式相当于:
这意味着表达式
相当于:
由于您将
m
定义为指向int
的指针,因此表达式m[3][3]
将执行以下操作:它将把m
视为指向int *
类型数组的第一个元素的指针。它将尝试读取此数组的第四个元素。它将把第四个元素当作指向int
类型数组的第一个元素的指针,并尝试读取该数组的第四个元素。但是,
m[3]
有一个不确定的(“垃圾”)值,所以m[3]
不会指向有效的数组。因此,通过解引用表达式m[3][3]
中的这个无效指针,您的程序正在调用undefined behavior,这意味着任何事情都可能发生,包括您在问题中描述的行为。因为你用了那句台词
我假设您的意图不是让
m
指向元素类型为int *
的数组的第一个元素,而是让m
指向int
元素的2D数组。换句话说,m
应该指向数组的第一个元素,其元素不是指针,而是数组。为了实现这一点,必须以不同的方式声明变量
m
。那条线
将声明变量
m
为指向int
的指针。这不是你想要的您希望它指向2D数组的第一个子数组,因此您希望声明一个指向10个int
元素的数组的指针。为此,必须使用以下语法:括号很重要,因为如果没有它们,你将声明一个
int *
类型的10个元素的数组,但你想声明一个指向10个int
元素的数组的指针。你的程序应该看起来像这样:
此程序具有以下输出:
请注意,在C中,与C++相比,generally discouraged没有必要转换
malloc
的结果。此外,通常最好检查
malloc
的返回值,以验证内存是否已成功分配。此外,当您不再需要内存时,您通常应该使用free
内存。sxpgvts33#
类型
int**
表示类型pointer to an (int *)
,* 不是 * 二维数组。所以
m[3][3] = 3;
在逻辑上等价于:...这可能是好的,如果这样的数组存在,数组中的指针实际上指向有效的内存位置。然而,在提交的代码中,整个缓冲区此时仍未初始化(即使初始化了也不会包含预期的指针数据),因此取消引用
p
会调用未定义的行为。jm81lzqq4#
其他答案都很棒。此外,这里有一些关于为什么的详细说明
这不是正确的用法。
malloc
只接受一个size_t
参数(您想要分配的字节数),您已经给了它这个参数,但是您以错误的方式导出了它。你应该根据 * 被指向的对象 * 来分配空间,这是指针类型的“上一级”。在这里,你已经声明了m
是一个int**
类型,这意味着它将指向int*
类型,这就是你应该用来派生malloc
的大小:这是分配内存时始终遵循的范例,馈送到
sizeof
的东西应该是被指向的东西。使用上面的malloc
,m
现在指向足够的空间来容纳10个int
指针,或10个int*
s。到目前为止一切都很好,但有一个更好的实践方法来做到这一点:
这里,
*m
是所指向的类型。而且无论m
类型是 , 都将始终为真。如果m
将类型更改为然后你需要把转换从
(int**)
改为(struct myStruct**)
,同样的,把参数改为sizeof
。在sizeof
的参数中使用*<myVar>
意味着,如果变量的类型发生了变化,维护工作会减少。最后是no need to cast the return from
malloc
。上述优点之一是,如果m
的类型发生变化,则会导致不必要的维护。最后,我们只剩下:假设
malloc
没有返回NULL
指针(你应该总是检查),你有足够的空间容纳10个int
指针。现在,你可以像其他答案中所示的那样循环遍历,并为这10个int
指针中的每一个分配空间:如上所述,
m[i]
是int*
类型,所以*(m[i])
是int
类型。但是如果m
的类型发生了变化,sizeof
的所有参数都会“自动”更新。sz81bmfz5#
您可以用途:
现在,您可以直接索引:
如果你的编译器支持VLA(可变长度数组),你可以有可变大小的数组:
行数和列数可以在运行时计算,而不需要在编译时设置。
在这两种情况下,使用
free(m)
释放分配的内存就足够了。