C 指向指针分配的指针

C Pointer to Pointer Allocation

我有有效的代码,但我不太明白为什么。我正在分配一个带有字符串的指针,将该字符串传递给一个函数,然后修改它。我很困惑,即使输入的字符串比原始字符串大得多,它似乎 运行 也很好。我希望它会抱怨覆盖内存,特别是因为原始指针不是 MALLOC/CALLOCed.

void changeArray(char *(*anArray)[3]);

函数声明

char *testArray[] = { "This is a test", "A Second Test", "A Third Test" };

指针声明&初始化

    changeArray(&testArray);

函数调用

void changeArray(char *(*anArray)[3]){
char userName[200];
printf("What is your name?:\t");
scanf("%199[^\n]s", userName);
*anArray[0] = userName; }

函数

    printf("Your name is: %s\n", testArray[0]);

在main中打印结果。

为什么 testArray[0] 无需重新分配内存就可以接受新字符串?更令人费解的是我在 locals 下查看结果,它看起来已损坏,但仍然打印正常。

+       [0] 0x00e2f850 "D`\x3\x1 øâ"    char *

我知道询问工作代码很奇怪,但我需要确保我了解正在发生的事情,以便我以后可以正确 implement/avoid 它。

您在这里看到的是未定义的行为。

你在 void changeArray() 中有一个本地数组 userName 并且你有指向它的指针,它只在函数中有效,一旦你从函数中 return 分配给它的内存本地数组被释放,因此在其范围之外访问此位置是未定义的。您甚至可能会看到崩溃

这是未定义的行为,未定义的行为在某些情况下按预期工作(并在其他情况下惨败)是合法的。

在您的例子中,您正在函数内的堆栈上分配 userName。当函数 returns 时, userName 占用的内存通常保持不变。但绝对不能保证。下一个函数调用可能会破坏您的字符串。异步信号处理程序也可能会破坏您的字符串,甚至在函数的 return 和 main().

中的下一行执行之间也可能发生这种情况

然而,未定义的行为是完全未定义的,您的程序完全有权在执行时擦除您的硬盘驱动器。所以尽量无条件地避免未定义的行为。

您混淆了字符串和指针。 C 中的 'string' 是内存中的字符数组,通常由指向数组开头的指针引用。所以当你声明

char *testArray[] = { "This is a test", "A Second Test", "A Third Test" };

这将 testArray 声明为一个包含 3 个指针的数组,并将每个指针初始化为指向一个静态字符串(字符数组可能在只读内存中)。

在您的 changeArray 函数中,您有:

char userName[200];
printf("What is your name?:\t");
scanf("%199[^\n]s", userName);
*anArray[0] = userName;

这将创建一个新的本地字符数组并用用户输入(可能是他们的名字)填充它,然后将通过引用作为参数传递的数组中的第 0 个指针指向此本地变量。一旦这个函数 returns,堆栈帧将被释放,指针悬空(指向现在释放的堆栈帧)因此它可能看起来有效但随后似乎随机变化。在退出范围后访问这样的局部变量是未定义的行为——任何事情都可能发生。