C 字符串常量存储

C 字符串常量存储,c,C,以下两个函数之间是否有任何差异?在这两种情况下,都不是返回局部变量的地址,而是使用f1 fn返回正确的值4,而不是f2。同样在第三种情况下,字符串常量并没有存储在堆栈中,所以当我们返回指针时,它可以正常工作。那么字符串常量存储在哪里呢 int* f1() { int* a=(int*)4; return a; } int* f2() { int a=4; return &a; } char* f3() { char* p="abcd"; return p; }

以下两个函数之间是否有任何差异?在这两种情况下,都不是返回局部变量的地址,而是使用f1 fn返回正确的值4,而不是f2。同样在第三种情况下,字符串常量并没有存储在堆栈中,所以当我们返回指针时,它可以正常工作。那么字符串常量存储在哪里呢

int* f1()
{
  int* a=(int*)4;
  return a;
}

int* f2()
{
  int a=4;
  return &a;
}

char* f3()
{
  char* p="abcd";
  return p;
}

它们之间都有区别:

第一个返回值为4的int*,请注意,它不指向值为4的变量,而是指向地址4。 第二个函数返回一个指针,指向一个包含4的变量,但实际上,这个指针无效,因为它指向一个已经返回的函数的局部变量,使用它将导致未定义的行为。 第三个根据定义返回指向char的指针,但实际上,根据实现,这是指向字符串文本的指针。它的问题是,作为函数return char*而不是const char*,可能会尝试修改返回缓冲区,这将再次导致未定义的行为。 f1将值4强制转换为一个地址,实际上指向内存中的某个位置。 f2返回局部变量的地址。取消引用此指针将是未定义的行为。 f3是指向字符串文字的指针。这是一个有效指针,因为字符串文字的生存期与程序生存期静态存储持续时间相同。具体存储该文本的位置由实现定义。操纵字符串文字的内容是未定义的行为。 在f1中,您明确指定了地址4,并返回了相同的值,而不是该地址的值。 局部变量分配在堆栈上,因此在f2中返回&a,返回的是堆栈上的地址,而不是内存中该地址处的4。当函数从堆栈中清除时,取消引用此地址会导致未定义的行为。 字符串文本在只读数据节上分配,请注意

字符arr[]=abcd;和char*ptr=abcd

第一个是字符数组,在堆栈上分配,而第二个是指向字符串文本的指针,该字符串文本不是在只读数据段上分配的指针


PS:我在这里假设了GCC/x86。

这两个函数之间有什么区别吗?您已经给出了3个函数!:作为记录,您不应该像那样返回指向堆栈变量的指针。在函数退出后,该内存很可能会被用于其他用途。难道不应该有人做出讽刺性的评论吗?这是家庭作业吗?洛莉,我知道我甚至没有费心在f3中键入答案,字符串文字实际上存储在哪里?不在堆栈中,对吗?因为我们可以在函数返回后访问。还有,为什么字符串文字常量是char*它只是语言构造还是其他东西???字符串文字存储在只读数据段而不是堆栈中,常量是因为它位于只读数据段中。@grv:如果您将f3的字符串改为:char p[]=abcd。。。编译器会自动将字符串文本的const内容复制到一个大小相同的堆栈缓冲区中,5个字节,每个字母1个字节,终止nul另一个字节。但是如果您将其定义为const char p[]=abcd。。。然后你会回到你以前的地方。。。缓冲区不会被复制,您的“p”数组不会被堆栈分配,也不会进行复制编译器只会使用字符串文字的存储空间来存储p[],其中一个区别有时很重要:……因为p是常量数组而不是字符指针,您可以获取其大小SizeOff并从中获取大小5,而无需使用strlen或手动计数字符。请注意,如果您尝试在原始代码上使用SizeOff,可能会得到4或8,这取决于您的应用程序是为32位还是64位平台编译的。在这种情况下,4或8与字符串的长度无关,它只是系统上指针的大小。f1不是指向地址0x4,而是指向内存中的某个地方吗?@ScottWilson正确。考虑到虚拟内存,我认为它在某个地方:每一个指针都不能用安全的方式获得,或者通过底层机器的核心知识是无用的,它的值并不重要。那么,所有的字符串文字都有静态存储吗?另外,为什么字符串文字被定义为const char*它只是语言构造还是有原因???@grv-请参阅我答案下的问题注释。f2中没有can。解除对该指针的引用是UB,无论是否刷新了什么。