返回C中带有常量char*的字符串
我试图理解为什么下面的字符串传递对我的错误字符串有效。我已经从一个更大的来源做了这个例子 我的问题是,;为什么我不需要为包含错误消息的char数组专门分配内存呢?我本以为我需要为字符串malloc一些内存,并使用err指针指示该内存的开始 这是因为它是一个返回C中带有常量char*的字符串,c,string,C,String,我试图理解为什么下面的字符串传递对我的错误字符串有效。我已经从一个更大的来源做了这个例子 我的问题是,;为什么我不需要为包含错误消息的char数组专门分配内存呢?我本以为我需要为字符串malloc一些内存,并使用err指针指示该内存的开始 这是因为它是一个常量字符*,还是因为我正在打印到stderr 我可能把这个问题写错了,这就是为什么搜索没有帮助我理解这个问题 const char * my_function(int a) { if (a != 1) return
常量字符*
,还是因为我正在打印到stderr
我可能把这个问题写错了,这就是为什么搜索没有帮助我理解这个问题
const char * my_function(int a)
{
if (a != 1)
return "a doesn't equal 1!"
else
return NULL;
}
int main(int a)
{
const char *err;
err = my_function(a);
if (err)
fprintf(stderr, "Message = %s\n",err);
return 1;
return 0;
}
字符串文本被分配为具有静态存储持续时间的const char数组,因此它们在程序的整个生命周期内都有效。它们所处的范围无关紧要——它们始终具有静态存储持续时间
这意味着您可以获取它们的地址(如果您返回字符串文本或将其存储在const char*变量的任意位置,则会隐式发生),而无需担心结果指针的生存期。字符串文本的存储永远不会用于其他内容。这是因为字符串存储在程序的数据部分。当您键入
“a不等于1!”
时,内存将被分配,该值将写入内存中
函数只返回指向该内存片的指针,
fprintf
乐于从中读取。返回的是字符串文字。它被保存在静态内存中,但有一个和其他字符串一样的地址。所以你可以随时查阅那个地址。问题是,如果您试图更改字符串文字,我认为这是一种未定义的行为。所有字符串文字都是在编译时分配的。当程序启动时,它们已经驻留在程序内存的只读部分中;它们不会在运行时分配。可以将它们视为常量字符数组。与任何常量
变量一样,它们在整个程序执行过程中保持有效。不要过于乐观。这是因为子例程中的字符串存储在共享段中(只读),可以在例程退出后返回。如果将其定义为char str[]=“your string”,则无法返回该值,因为它在堆栈上是“已分配”的。堆栈指针将在子程序结束时恢复 请注意,main()
将始终返回1
int main(int a)
{
const char *err;
err = my_function(a);
if (err)
fprintf(stderr, "Message = %s\n",err);
return 1;
return 0;
}
返回1
缩进,就好像它在if(err)
下一样,但它不是。你真正拥有的是:
int main(int a)
{
const char *err;
err = my_function(a);
if (err)
fprintf(stderr, "Message = %s\n",err);
return 1;
return 0; # Never gets executed.
}
你想要的是:
int main(int a)
{
const char *err;
err = my_function(a);
if (err) {
fprintf(stderr, "Message = %s\n",err);
return 1;
}
return 0;
}
正是因为这个原因,我总是在块周围使用大括号,即使它们不是严格必需的。请参阅:分配了多少内存?刚好够我返回的字符串吗?如果我有另一个函数将常量char*返回到同一地址怎么办?但是更长了吗?刚好够你的字符串使用,请查看生成的程序集以了解它是如何工作的。我不明白你的第二个问题,“但是更长了”是什么意思?另一个返回相同指针的函数可以正常工作。您可以在
printf
函数中使用%p
查看指针指向的实际地址。@Markus字符串文字在程序编译时被“分配”(运行时,操作系统将代码和数据复制到内存中,基本上为它们分配实际内存)。它们存储在二进制文件中。您可以在Unix上使用strings
之类的工具查看它们。“所有字符串文本都是在编译时分配的。”-对我来说,这是所有答案中最有用的部分。“所有字符串文本都是在编译时分配的。”这句话真的正确吗?我相信编译时不会分配任何内容。如果它是在编译时分配的,那么它什么时候被释放呢?@Kolyunya Link time,如果你很挑剔的话。字符串文本通常放在名为.rodata
的内存段中。这是因为子程序中的字符串存储在共享段(只读)中,可以在例程退出后返回。如果将其定义为char str[]=“your string”,则无法返回该值,因为它在堆栈上是“已分配”的。堆栈指针将在子程序结束时恢复。所以@Ludin的答案在这里只是局部的。