我正在使用这本书学习 C C 编程:现代 Approach并且我对指针的使用有一些疑问 并引用超出范围的变量。我整理了三个例子 说明我的疑问。
首先,我们有这个:
char *f() {
char p[] = "Hi, I'm a string";
return p;
}
据我了解,这段代码是有问题的,因为
p
是一个类型变量
位于函数 chars
范围内的 f()
数组。当我返回p
时,我正在使用
数组的名称作为指向第一个元素的指针,但由于变量只是
在函数作用域内有效,当我返回 p
时,我最终得到一个指向
无效的变量(悬空指针?)。结果,如果我尝试使用 p
在函数之外,我遇到了分段错误。
这是正确的吗?
接下来我有这个:
char *g() {
char *p = "Hi, I'm a string";
return p;
}
这与之前的情况非常接近,但似乎没问题,我可以访问字符串 从函数外部,我没有收到编译器的警告(就像我在 之前的案例)。我不明白为什么它会起作用,
p
被声明为char
指针,所以我假设,当它初始化时,它指向第一个字符
字符串文字,与作为数组时相同,是不是这样,或者实际上是这样
在我的特定背景下,无玷污的行为有效吗?
最后,我有这个:
char *h() {
char *p = malloc(17 * sizeof(char));
strcpy(p, "Hi, I'm a string");
return p;
}
这与前面的示例有什么不同吗?我想这不是,我只是 手动分配内存。这似乎也让我可以访问整个字符串 在函数之外,但我和前面的例子有同样的疑问。
我是这样测试三个功能的:
int main(int argc, char *argv[]) {
// This causes a segmentation fault
printf("%s\n", f());
// These two work ok
printf("%s\n", g());
printf("%s\n", h());
}
你能帮助我更好地了解这里发生了什么吗? 预先感谢!
正如您所正确指出的那样,第一个函数返回无效指针,因为在函数内声明并具有自动存储持续时间的数组在退出函数后将不再存在。取消引用此类指针会导致未定义的行为。
在第二个函数中,返回一个指向字符串文字的第一个字符的指针。字符串文字具有静态存储期限。因此,使用的字符串文字在退出函数后将仍然存在,因此函数返回一个有效的指针。
在第三个函数中动态分配内存。在调用 free 函数之前它不会被释放。所以返回的指针是有效的。
要释放分配的内存,您可以在 main 中编写
char *p = h();
if ( p != NULL ) printf("%s\n", p);
free( p );