繁体   English   中英

C 编译器不提供结束 null 值的情况有哪些?

[英]What are the cases in which the C compiler does not provide an ending null value?

我一直在学习 C,并且来自更高级的语言,这绝对是新事物! 我知道 arrays 以'\0'值终止,我想知道编译器不提供此功能的实例是什么? 例如:

int main() {
    int val;
    scanf("%d", &val);
    char arr[val + 1]; 
    arr[val] = '\0'; // The null value must be stated or something unpredictable occurs  
    for (int i = 0; i < val; i++ ) {
        arr[i] = 'a';
    }
    printf("This is the output:\n%s", arr);

    char arr2[5]; // This works perfectly fine
    for (int i = 0; i < 5; i++ ) {
        arr2[i] = 'a';
    }
    printf("This is the output:\n%s", arr2);
}

所以我得到的概念是,当我们要么

  1. 动态分配 memory 或
  2. 在编译时不知道数组的大小

当编译器不能/不提供结束 null 值时。 如果是这种情况,在使用 arrays 时是否还有其他需要注意的情况?

编辑:在被指出之后, arr2在这个意义上没有提供结束零终止符,尽管它打印了我所期望的。

(我不确定这是否回答了您的问题,但我认为可以。如果没有,请告诉我删除它,我会这样做)编译器仅在您初始化文字时提供:

const char str[] = "Hello, world!"

其他任何时候(出于我认为的所有意图和目的)编译器都不会为您执行此操作。 一些函数(在标准库内部和外部)会为您添加一个\0 ,但解决这个问题的最佳方法是查看文档。

Arrays 一般不以 '\0' 结束

字符串是一种特定类型的字符数组,根据定义以 '\0' 结尾。 这意味着 C 风格的字符串是一个以 '\0' 结尾的“char 数组”。即使:

  • 在分配的“字符数组”结束之前遇到第一个 '\0'
  • 第一个 '\0' 作为分配的“char 数组”的最后一个元素遇到
  • 在分配的“char 数组”的最后一个元素之后遇到第一个 '\0'

注意最后一个,它会引起各种各样的麻烦。 这意味着作为开发人员,您有责任确保在程序运行时创建的任何字符串的末尾都有一个 '\0'。 "hello"这样的 C 风格字符串的字符数组将以 '\0' 结尾,因为编译器将创建支持数组并在末尾插入该字符。

开发软件的错误包括没有确保在更改字符串时,所有字符串都以“\0”结尾。 如果您在代码中写入这样的错误,则某些字符串操作(非安全操作)将继续读取的可能性非零,直到它发生在 '\0' 或退出程序分配的 memory .

第一种情况除了错误的程序 function 外,还可能导致安全漏洞(称为注入攻击)。 第二种情况可能会导致您的程序以 SEGFAULT 消息终止。

我知道 arrays 以 '\0' 值终止,

不,字符串以零字节终止(可以表示为'\0' )。 事实上,这是字符串的定义特征之一。 但是在 C 中,字符串是数据,而不是数据结构。 没有“字符串”数据类型,虽然区别有点小,但包含字符串的数组与该字符串本身并不相同。 除其他外,数组可能大于字符串内容 + 终止符。 Arrays不保证以任何特殊值终止,除非它们的内容可能指示(例如,包含字符串文字的数组)。

我想知道编译器不提供这个的实例是什么?

编译器负责确保 arrays 中的字符串文字终止,它会自动提供以包含它们。 它还将默认初始化否则未初始化的 arrays 在文件 scope 或static中声明,这意味着对于算术类型的元素(包括字符类型)初始化为零。 当存在显式初始化程序(不是赋值)时,它还将默认初始化任何数组的未初始化成员,包括自动成员。仅覆盖某些成员。 编译器没有提供零终止的其他责任。

在大多数情况下,标准库的字符串函数依赖于它们的输入是否以零结尾(即真正的字符串),并且它们提供以零结尾的 output 字符串。 但也有例外。

类似地,在大多数情况下,接受字符串输入的 I/O 函数期望真正的零终止字符串,而提供字符串输出的 I/O 函数则确保零终止。 但同样,也有例外。

当它成功分配 memory 时,标准库 function calloc()对其进行零初始化。 malloc()realloc()不这样做。

我认为这涵盖了与该问题相关的大多数标准库函数,但这是您需要注意的事情。 不过,一般来说,function 文档将明确说明 function 接受或产生未终止的“字符串”的任何情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM