为什么这个结构已经用字段中的数据初始化了?

时间:2013-11-15 19:22:10

标签: c++ c struct undefined-behavior arrays

我正在使用 C 编写的库,我自己的程序在 C ++ 中。他们 typedef 这样的结构:

typedef struct tagCtxt
{
    char     iadl1[50+1];
    char     iadl2[50+1];
    char     iprurb[28+1];
    char     iadl3[50+1];
} PARM;

在我的一个方法中,我构造它并立即打印其中一个字段的值:

PARM parm1;
cout << "'" << parm1.iadl3 << "'" << endl;

正如所料,它是空白/空白:

''

现在我这样做,创建parm2

PARM parm1, parm2;
cout << "'" << parm1.iadl3 << "'\t'" << parm2.iadl3 << "'" endl;

然后我明白了:

''    'x��'

第二个的输出有所不同。有时它看起来像�ǰǰ等。

此行似乎可以解决症状:

memset(&parm2.iadl3, 0, sizeof(parm2.iadl3));

但问题是什么?为什么char数组非空为第二个?而不是第一个?

请记住,我的程序编译为 C ++ 但我正在使用的头文件定义的类型在 C 中。这有什么区别吗?我像这样包含头文件:

extern "C"
{
    #include "parm.h"
}

7 个答案:

答案 0 :(得分:4)

这是undefined behavior自动变量的初始值是不确定的,您需要在使用它们之前初始化变量。

<{1}}部分<{1}} 对象的存储持续时间在覆盖静态变量之后说(强调我的 ):

  

对于没有可变长度数组类型的对象,其生命周期会延长   从进入与之关联的块直到该块的执行结束   无论如何。 [...] 对象的初始值是不确定的。 [...]

indeterminate value 的定义如下:

  

未指定的值或陷阱表示

C99 draft standard部分6.2.4 初始化 12 表示(强调我的):

  

如果没有为对象指定初始化程序,则默认初始化该对象;如果未执行初始化,具有自动或动态存储持续时间的对象具有不确定值。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见3.6.2。 - 后注]

开始理解某些形式的未定义行为的好地方是C++ draft standard幻灯片。

答案 1 :(得分:2)

“正如预期的那样,它是空白/空的:”不,这不是预期的。 C ++没有初始化变量的值(除了它的数据类型提供了一个构造函数来完成这项工作,或者是一个具有静态存储持续时间的东西)。

正如沙菲克所说,阅读未初始化的数据有不明确的行为。

答案 2 :(得分:1)

与C / C ++无关。

一般情况下,你没有明确设置的内存(比如你所做的memset操作)包含未定义的值。

“预期”不是0。

答案 3 :(得分:1)

C和C ++不保证局部变量的值。它们具有垃圾值,具体取决于分配时该内存地址的内容。要使用它们,必须使用值初始化它们。

全局变量不是这样。默认情况下,它们初始化为0。

答案 4 :(得分:1)

char     iadl1[50+1];

将保留一块足以存储51个字符的内存块

但是,它并不能保证你的那块内存都是空的,在你的情况下恰好是空的。通常,在访问数组之前使用memset来初始化数组是最好的方法。

memset( iadl1, '\0', sizeof(char)*51);

答案 5 :(得分:1)

只有静态变量具有预初始化的值。在堆栈上创建的变量(即局部变量)具有垃圾值,因此在初始化之前不应使用。

答案 6 :(得分:0)

一种方法是定义构造函数来初始化参数

typedef struct tagCtxt
{
    tagCtxt()
    {
     memset( iadl1, '\0', sizeof(char)*51);
     memset( iadl2, '\0', sizeof(char)*51);
     memset( iprurb, '\0', sizeof(char)*29);
     memset( iadl3, '\0', sizeof(char)*51);
    }
    char     iadl1[50+1];
    char     iadl2[50+1];
    char     iprurb[28+1];
    char     iadl3[50+1];
} PARM;