ANSI c95数组初始化保证

问题描述 投票:1回答:3

我正在尝试寻找证实或与之相矛盾的文件,char test[5]="";导致将缓冲区初始化为与memset(test,'\0',sizeof(test));相同的所有空字符,但无法找到(或理解/解密)任何内容。谢谢

c arrays language-lawyer string-literals aggregate-initialization
3个回答
1
投票

这不是您问题的完整答案,但可以消除其他答案中的错误信息

在ANSI C89中,相关标准文本为(第3.5.7节):

如果未自动初始化具有自动存储期限的对象,则其值不确定。

字符类型的数组可以由字符串文字初始化,可以选择用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括结尾的空字符)将初始化数组的成员。

它仅指定与字符串文字相对应的数组元素的初始化。因此,尾随数组元素未显式初始化,因此具有不确定的值。

还有一段:

如果初始化器在列表中]少于集合的成员,则聚合的其余部分应隐式地初始化为具有静态存储持续时间的对象。”>

但是这并不适用,因为我们不是从列表中初始化的(“ list”是指用大括号括起来的列表,而不是字符串文字)。


在ISO C99 + TC2(n1124)中,新文本已添加到后一段(现在称为6.7.8 / 21):

如果括号括起来的列表中的初始化程序少于集合中的元素或成员,或用于初始化已知大小的数组的字符串文字中的字符少于该数组中的元素

,集合的其余部分应与具有静态存储持续时间的对象隐式初始化。

意味着尾随数组元素被初始化为空字节。


我无法找到纯C99(即没有任何技术勘误)或C95(ISO / IEC 9899:1990 / AMD1:1995)的免费副本。因此,无法确切说明C89和C99 + TC2之间的哪一点已更改。另外,C99基本原理文档中未提及该主题。

希望其他人那里有这些文件(或倾向于从ISO商店购买它们!)可以提供准确的答案。

从C标准(6.7.9初始化)

10如果具有自动存储持续时间的对象未初始化显然,它的值是不确定的。如果对象具有静态或未明确初始化线程存储持续时间,则:

—如果具有指针类型,则将其初始化为空指针;

—如果具有算术类型,则将其初始化为(正或无符号)零;

...

21如果括号括起来的列表中的初始化程序少于是集合中的元素或成员,或者字符串文字,用来初始化一个已知大小的数组是数组中的元素,聚合的其余部分应为隐式初始化为与具有静态存储的对象相同持续时间。

这意味着在此声明中

char test[5] = "";

数组的所有五个元素都初始化为零。第一个元素通过字符串文字的结尾零显式初始化,而所有其他元素则与具有静态存储期限的对象一样隐式初始化。

至少从C99标准开始有效。

下面有一个演示程序,显示了用零初始化字符数组的不同方法。

#include <stdio.h>

int main(void) 
{
    enum { N = 5 };

    char s1[N] = "";
    char s2[N] = { "" };
    char s3[N] = { 0 };
    char s4[N] = { [0] = 0 };
    char s5[N] = { [N-1] = 0 };

    char * s[] = { s1, s2, s3, s4, s5 };

    for ( size_t i = 0; i < sizeof( s ) / sizeof( *s ); i++ )
    {
        for ( size_t j = 0; j < N; j++ )
        {
            printf( "%d", s[i][j] );
        }
        putchar( '\n' );
    }
    return 0;
}

程序输出为

00000
00000
00000
00000
00000

从代码清晰的角度来看,如果数组的目的是保存字符串,则

char test[5] = "";

用零长度的字符串初始化数组,其余字节无关紧要。如果它们确实很重要,则该数组实际上不是字符串,应该使用

char test[5] = {0};

进行澄清。


1
投票

从C标准(6.7.9初始化)


0
投票

从代码清晰的角度来看,如果数组的目的是保存字符串,则

© www.soinside.com 2019 - 2024. All rights reserved.