亲爱的明智的堆栈交换器,我已经让自己长达8个小时的连续思考,但仍然无法找到对以下代码的正确解释:
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char** pWords = calloc(10, sizeof(char*));
*(pWords + 1) = malloc(10);
strcpy_s(*(pWords + 1), 10, "Test sent\0");
printf("The string is: %s", *(pWords + 1));
return 0;
}
这个输出是:
The string is: Test sent
我已将内存分配解释为:
+-------+-------+-------+-------+......
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|......
+-------+-------+-------+-------+......
^ ^
| |
| |
pointer(let) <-------malloc(10)
|
|
pWords <------calloc(10, sizeof(char*))
我基本上不理解涉及间接级别和指针的部分:
首先,pWords被声明为指向指针的指针。 (例如,我认为它是pointer
。然后只使用一个&#34; *&#34;符号将引用此pointer
,对吧?那么当它是什么时,它会指向什么?初始化为:calloc(10, sizeof(char*))
?
为什么*(pWords + 1)
将用于访问使用两个间接**
级别声明的指针的内容?不应该是**(pWords + 1)
吗?
答案 0 :(得分:5)
在处理C中的字符串时很容易处于混乱状态。字符串在C中并不是真正的一等公民,因此我们有一个使用指向第一个字符的指针来引用它们的约定< / strong>即可。如你所知,字符串的结尾是由NUL字符表示的。
您分配内存:
char** pWords = calloc(10, sizeof(char*));
在这里,您创建了一个包含指针指向char的10个指针的数组(您将使用它来处理10个字符串)。接下来,指出这10个指针中的第二个指向一些新内存:
*(pWords + 1) = malloc(10);
pWords[1] = malloc(10); /* this is exactly equivalent, and more idiomatic */
现在,您将第二个指针作为目标参数传递给strcpy_s()
。它将写入指向char
及其后续的,用NUL字符结束以标记字符串的结尾:
strcpy_s(pWords[1], 10, "Test sent");
然后你打印字符串;为此,您将相同的指针(您分配的十个指针中的第二个)传递给printf()
。
printf("The string is: %s\n", pWords[1]);
几个旁注:
free()
或malloc()
分配的内存calloc()
。在程序结束时,放弃它通常是安全的,但是在调试时至少可以选择清理它仍然会发现它很有帮助。当您在代码中的其他位置查找实际内存泄漏时,这可以帮助您。calloc()
为指针保留内存并不能保证指针是空指针。它很棘手且令人困惑,因为C语言中有一种神奇的功能可以在您需要时将代码中编写的0
转换为正确类型的空指针,即使您的目标平台实际上并未将空指针表示为零位如果您为strcpy
函数提供一个带有嵌入式\0
的字符串文字,它会将该NUL视为字符串的结尾。你可以证明这一点:
printf("%s\n", "foo\0bar");
“foo”后打印将停止,并且不会使用“bar”。
char **pointer
与char *pointer[number]
不完全相同。前者是指向char
的指针(并且可以指向数组),而后者是 {{1}的数组}。再次,它变得令人困惑,因为如果我们打算将它作为一个(使用数组索引或其他指针算法),我们倾向于将char*
和朋友的内存称为“数组”。答案 1 :(得分:1)
char** pWords = calloc(10, sizeof(char*));
这就像创建一个指针数组。在这种情况下,你创建的数组包含10个char指针。
*(pWords + 1) = malloc(10);
你在这里做的是为第二个指针分配空间。 *(pWords + 1)取每个指针指向的地址。
strcpy_s(*(pWords + 1), 10, "Test sent\0");
在此处复制指针的已分配空间中的字符串。
printf("The string is: %s", *(pWords + 1));
在这里你只需打印指针的内容。