c中的间接水平

时间:2017-03-10 10:18:25

标签: c pointers

亲爱的明智的堆栈交换器,我已经让自己长达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)吗?

2 个答案:

答案 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]);

几个旁注:

  • 您没有检查所调用的任何函数的返回值,以查看它们是否报告错误。我假设这只是为了让你的问题简短,但请记住,这种错误检查在C中是非常重要的 - 如果你不检查,你的程序很可能会在一个神秘的令人费解的方式。
  • 您通常free()malloc()分配的内存calloc()。在程序结束时,放弃它通常是安全的,但是在调试时至少可以选择清理它仍然会发现它很有帮助。当您在代码中的其他位置查找实际内存泄漏时,这可以帮助您。
  • 使用calloc()为指针保留内存并不能保证指针是空指针。它很棘手且令人困惑,因为C语言中有一种神奇的功能可以在您需要时将代码中编写的0转换为正确类型的空指针,即使您的目标平台实际上并未将空指针表示为零位
  • 如果您为strcpy函数提供一个带有嵌入式\0的字符串文字,它会将该NUL视为字符串的结尾。你可以证明这一点:

    printf("%s\n", "foo\0bar");
    

    “foo”后打印将停止,并且不会使用“bar”。

  • char **pointerchar *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));

在这里你只需打印指针的内容。