C 编译器差异? Char 中的 NUL 控制字符

标签 c

下面的 C 代码将生成 char 数组,但显式添加或不添加 Null 字符。结果在两个编译器中是出乎意料的,我不知道为什么我们甚至必须显式添加 Null 字符?

//
//  stringBugorNot.c
//  
//
//

#include <string.h>
#include <stdio.h>


 int main(void)
{
     char aString[3] = {'a', 'b','c'};
     char bString[4] = {'a', 'b', 'c', '\0'};

     printf("\n");
     printf("len of a is: %lu\n", strlen(aString));
     printf("len of b is: %lu\n", strlen(bString));

     printf("\n");

     //Portion A

     printf("last element of a is: '%c'\n", aString[strlen(aString)]);
     printf("last element of b is: '%c'\n", bString[strlen(bString)]);

     printf("\n");

     //Portion B

     printf("last element of a is: '%c'\n", aString[strlen(aString) - 1]);
     printf("last element of b is: '%c'\n", bString[strlen(bString) - 1]);


}

评论

+clang 会给出运行时错误,因为“aString”越界..是有道理的 +gcc 不会给出任何错误,只是按照预期输出“无”null。但也许 gcc 更聪明,为我添加了 null ?实际内存大小是否不同?

<小时/>

Clang 输出 ---->

a 的长度为:3

b 的长度为:3

bugOrNot.c:16:41:运行时错误:索引 3 超出类型“char [3]”的范围

a 的最后一个元素是:''

b 的最后一个元素是:''

a 的最后一个元素是:'c'

b 的最后一个元素是:'c'

<小时/>

GCC 输出 ---->

a 的长度为:9

b 的长度为:3

a 的最后一个元素是:''

b 的最后一个元素是:''

a 的最后一个元素是:''

b 的最后一个元素是:'c'

最佳答案

您看到的意外行为在 C 标准中称为未定义行为 (UB):

  • aString 上调用 strlen 是 UB,因为没有 null 终止
  • 在未定义索引处取消引用 aString 为 UB,除非索引为 0、1 或 2
  • gcc 可能会通过在 4 字节边界对齐 bString 无意中插入空终止符。但这并没有改变它仍然是 UB 的事实。

关于C 编译器差异? Char 中的 NUL 控制字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52012445/

相关文章:

c - 在 Linux 下使用信号量和共享内存

c - 使用参数从控制台运行程序

c++ - 如何确定 Win32 线程是否已终止?

c - 如何为 Xeon Phi 编译 C 代码 (Windows 10)

c - 如何使用 canopen 从命令行打开文件

c - 使用链接列表读取文本文件

c - 客户端断开连接后是否可以从客户端套接字读取数据?

c - 我是否要转换 malloc 的结果?

使用标准 I/O 和系统调用制作文件副本的 C 程序

c - 使用 getchar() 在 C 中进行 UTF-8 编码