首页 文章

C和C:自动结构的部分初始化

提问于
浏览
62

例如,如果 somestruct 有三个整数成员,我一直认为在C(或C)函数中执行此操作是可以的:

somestruct s = {123,};

第一个成员将初始化为123,最后两个成员将初始化为0.我经常对自动数组执行相同操作,编写 int arr[100] = {0,}; 以便将数组中的所有整数初始化为零 .

最近我在GNU C Reference Manual中读到:

如果未初始化结构变量,则效果取决于它是否具有静态存储(请参阅存储类说明符) . 如果是,则使用0初始化具有整数类型的成员,并将指针成员初始化为NULL;否则,结构成员的 Value 是不确定的 .

有人可以告诉我关于部分自动结构和自动阵列初始化的C和C标准吗?我在Visual Studio中执行上面的代码没有问题,但我希望与gcc / g兼容,也可能与其他编译器兼容 . 谢谢

5 回答

  • 15

    链接的gcc文档没有谈到 Partial Initialization 它只是谈到 (Complete)InitializationNo Initialization .

    什么是部分初始化?

    标准没有定义对象的部分初始化,要么是完全初始化,要么是无初始化 . 部分初始化是一种非标准术语,通常指的是您提供一些初始值设定项但不是全部的初始值,即:初始化程序的数量少于数组的大小或初始化的结构元素的数量 .

    例:

    int array[10] = {1,2};                    //Case 1:Partial Initialization
    

    什么是(完整)初始化或无初始化?

    初始化意味着在创建变量的同时为创建的变量提供一些初始值 . 即:在相同的代码声明中 .

    例:

    int array[10] = {0,1,2,3,4,5,6,7,8,9};    //Case 2:Complete Initialization
    int array[10];                            //Case 3:No Initialization
    

    引用的段落描述了 Case 3 的行为 .

    有关部分初始化( Case 1 )的规则由标准很好地定义,并且这些规则不依赖于正在初始化的变量的存储类型 .
    AFAIK,所有主流编译器都100%遵守这些规则 .


    有人可以告诉我C和C标准对于部分自动结构和自动阵列初始化的说法吗?

    C和C标准保证即使整数数组位于自动存储上,并且如果括号括起的列表中的初始化程序较少,则未初始化的元素 must 也会初始化为 0 .

    C99 Standard 6.7.8.21

    如果括号括起的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符数少于数组中的元素,则聚合的其余部分应与具有静态存储持续时间的对象隐式初始化 .


    在C中,规则的陈述略有不同 .

    C++03 Standard 8.5.1 Aggregates
    Para 7:

    如果列表中的初始值设定项少于聚合中的成员,则未明确初始化的每个成员都应进行值初始化(8.5) . [例子:struct S {int a; char * b; int c; };
    S ss = {1,“asdf”};
    使用“asdf”初始化ss.a,使用“asdf”初始化ss.b,使用int()形式的表达式的值初始化ss.c,即0 . ]

    在定义值初始化时,
    C++03 8.5 Initializers
    Para 5:

    对T类型的对象进行值初始化意味着: - 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T的默认构造函数(如果T的默认构造函数被调用(如果T没有可访问的默认构造函数); - 如果T是没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都是值初始化的; - 如果T是数组类型,则每个元素都是值初始化的; - 否则,对象被零初始化

  • 89

    最新的gcc版本也允许同时“部分”初始化和zeromem:

    typedef struct{
      int a,b,c;
    }T;
    
    T s = {0, .b=5};
    

    struct成员现在将具有以下值: a=0, b=5, c=0

    我没有关于其他编译器是否允许这样做的任何信息:p

  • 4

    在C中,对象永远不会被部分初始化 - 如果它们的任何部分被初始化,则初始化整个对象(以及递归的所有子对象) . 如果未提供显式初始化器,则元素初始化为"zero of the appropriate type" .

    您的问题中的引用是指完全省略整个对象的初始化程序,而不是指子对象缺少初始化程序时 . 例如,假设 arr 具有自动存储持续时间,那么:

    int arr[100] = { 123 };
    

    arr[0] 初始化为 123 ,将 arr 的每个其他元素初始化为 0 . 鉴于此:

    int arr[100];
    

    留下 arr 未初始化的每个元素 . 引用的是后一种情况 .

  • 0
    // You can use something like this:
    typedef struct {
    
        ...;
    
        ...;
    
    } somestruct;
    
    // Declaration of struct
    somestruct st;
    
    // Initialising with 0. It does not depend on the size of the
    // structure and the number of elements in it.
    // memset() initialisation doesn't care if struct is static or dynamic.
    // but don't forget to use st instead &st to dynamic.
    memset(&st, 0, sizeof(somestruct));
    
  • 0

    如果变量是全局变量和静态变量,则它在二进制文件的全局区域中分配,该区域被初始化为零 . 如果变量是本地的,它在堆栈中分配,编译器不会初始化堆栈中的内存 . (某些调试版本可能会初始化,但发布版本永远不会这样做)

    如果变量是在Heap中分配的,则编译器也不会对其进行初始化 .

相关问题