char** args = (char**)malloc(MAX_ARGS*sizeof(char*));
和
char* args = (char*)malloc(MAX_ARGS*sizeof(char*));
请解释这两种声明之间的区别。为什么我们需要 2 星,为什么需要 1 星?
在这两种情况下,强制转换都是不必要的,并且可以掩盖错误;我将在下面删除演员表。(malloc()
返回 a void*
,它可以隐式转换为指向任何对象的指针。)
char **args = malloc(MAX_ARGS*sizeof(char*));
这定义args
为一个指向字符的指针,并将其初始化为指向一块足够大的内存来保存MAX_ARGS
元素,每个元素都是一个char*
. 完成此操作后,您将需要为这些char*
元素分配值,可能使它们指向字符串。
char *args = malloc(MAX_ARGS*sizeof(char*));
这是合法的,但几乎可以肯定是一个逻辑错误。 args
是一个指向字符的指针,这意味着它可以指向单个char
对象,也可以指向元素数组的第一个char
元素。但是您正在分配可以容纳MAX_ARGS
指针的内存。
更有可能做的是:
char *s = malloc(MAX_LEN);
这将导致s
指向可以保存MAX_LEN
char
元素的内存区域(长度为 的字符串MAX_LEN - 1
)。(请注意,sizeof (char) == 1
根据定义。)
有一个有用的技巧可以避免类型不匹配。FOO*
对于任何类型,类型的指针都FOO
需要指向一块足够大的内存,以容纳旧的一个或多个类型的元素FOO
。如果你写:
ptr = malloc(count * sizeof *ptr);
and ptr
is a FOO*
, then与 --sizeof *ptr
相同,sizeof (FOO)
但如果您稍后更改ptr
为pointer to
BAR`,则不必更新该行。
在您的情况下,指向的类型本身就是一个指针,因此您可以编写:
char **args = malloc(MAX_ARGS * sizeof *args);
当你调用 时malloc
,你应该总是检查它是否成功,如果失败则采取一些行动——即使那个行动是用错误信息终止程序:
if (args == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
两颗星表示指向指针类型到数据类型的指针。所以在 char** 的情况下,这意味着创建一个 char*[MAX_ARGS] 数组。
因此,对于这种情况,以下内容将是有效的,因为args[n]是char*:
args[0] = (char*)strdup("aaa");
args[1] = (char*)strdup("bbbb");
args[2] = (char*)strdup("ccccc");
注意:您应该记住在释放 args 之前释放数组的每个成员,否则指针会丢失。
使用单个星,它只是一个指向数据的指针,本质上您正在编写 char[MAX_ARGS*sizeof(char*)]
对于这个args[n]是一个char类型:
args[0] = 'a';
args[1] = 'b';
args[2] = 'c';
使用这个 char 数组,您将创建一个简单的字符数组,也称为 c 样式字符串。
2 颗星就像矩阵(或二维数组)。第一个 malloc 只为第一行获取内存(您必须遍历其元素,使第二个 malloc 为其他的保留空间)。