当前位置: 首页 > 知识库问答 >
问题:

有人能解释一下为什么这是可能的吗?[重复]

张博涛
2023-03-14
int main ()
{
   char *strA = "abc";
   int tam_strA = strlen(strA);
   
   char strB[tam_strA];
   strB[0] = 'a';
   strB[1] = 'b';
   strB[2] = 'c';
   strB[3] = 'd';
   strB[9] = 'z';
   
   printf("%c", strB[9]);
   
   return 0;
}

它通常会打印“z”。为什么它不返回分段错误?因为我试图访问一个不应该存在的索引,因为strB的大小(索引数量)等于tam_strA,它等于3。

另外,做char strB[strlen(strA)];有什么不同/问题吗?

共有2个答案

狄海
2023-03-14

只有在访问你不拥有的内存时,你才会出现分段错误。你拥有你的整个堆栈。strB[9]在操作系统看来是有效的内存访问。你不应该这样做的原因是编译器不知道你在使用那个内存,所以它可能会决定将那个内存用于其他用途。这也有助于提高可读性,最大限度地减少程序员的错误。而且,标准将使用未声明的内存定义为未定义的行为,因此你不能安全地使用它。声明一个变量,如int x;(或数组),告诉编译器您将使用x处的内存。

这实际上与这个问题有关:为什么定义数组之外的第一个元素默认为零?。阅读那边更详细的答案。

濮阳繁
2023-03-14

C语言没有阻止您访问无效内存的规范,也不能保证出现分段错误。唯一的promise是,如果试图访问无效内存,将导致未定义的行为。

分割错误是可能的结果之一,而不是唯一的结果。

也就是说,唯一的问题是

 char strB[strlen(strA)];

也就是说,strB的长度不足以保存strA中的内容,因为它缺少一个字节来保存空终止符。当然,按字节使用是可以的,但是如果您想复制内容(或与strA相同长度的任何内容)并将strB用作字符串,您将运行经过分配的内存(在没有空终止符的情况下),调用未定义的行为。

 类似资料: