Jac*_*row 5 c memory struct pointers scope
#include <stdio.h>
#include <stdlib.h>
struct Test {
const char *str;
};
void test_new(Test *test) {
char *s = malloc(100);
s[0] = 'H';
s[1] = 'i';
s[2] = '\0';
test->str = s;
}
int main(void) {
struct Test test;
test_new(&test);
puts(test.str);
free(test.str);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是允许的吗?将结构成员分配给函数中的局部变量(字符指针)test_new?(被test->str = s允许?)
我听说数组变量本来就是局部变量,但在函数结束后会被释放。我想知道这是否适用于分配内存的局部变量。
像这样:
char *test(void) {
char s[100];
return s;
}
Run Code Online (Sandbox Code Playgroud)
s将在函数结束时消失,所以我想知道这是否适用于我的结构,特别是我不是返回,而是更改成员。
test->str将结构成员指针(即)分配给另一个动态内存分配的指针(即)是否安全s?
从test_new函数中我们看一下这两行:
// 1
char *s = malloc(100);
// 2
test->str = s;
Run Code Online (Sandbox Code Playgroud)
当1你有这样的事情之后:
+---+ +--------------------------------------------+ | s | --> | 由 malloc 分配的内存... | +---+ +--------------------------------------------+
然后当2你有这样的事情之后:
+---+
| s | ----------\
+---+ \ +--------------------------------------------+
>--> | 由 malloc 分配的内存... |
+------------+ / +----------------------------+
| 测试->str | --/
+------------+
然后一旦test_new返回,函数中就只有这个main:
+----------+ +----------------------------+ | 测试.str | --> | 由 malloc 分配的内存... | +----------+ +----------------------------+
这完全没问题。
在您的函数中完成的分配/分配test_new是允许的并且是安全的。这是因为该char *s = malloc(100);行在堆上(而不是在“本地”堆栈上)分配内存,并且该test->str = s;行将指向已分配内存的指针分配给通过引用传递的结构的成员。因此,调用代码的结构变量中的该成员将按照您的意图进行修改。
错误的地方(使用第二个片段中的本地内存示例)将是这样的:
void test_bad(Test *test) {
char s[100]; // Local memory - gone when function returns
s[0] = 'H';
s[1] = 'i';
s[2] = '\0';
test->str = s; // Pointer member of structure will be invalid after the return.
}
Run Code Online (Sandbox Code Playgroud)
上面的错误代码将编译(语法上是正确的),但任何像样的编译器都会(或应该)警告您使用指向局部变量的指针。