[C语言] 结构体变量使用{}初始化

iceway 2009-10-30 04:32:02
先看源代码:
#include <stdio.h>

struct s1
{
int a1;
char a2;
char *a3;
long unsigned int a4;
double a5;
};

struct s2
{
struct s1 b1;
struct s2 *b2;
};

struct s2 s;

#define FORMAT "%08x %02x %08x %08x %08x%08x, %08x"
#define VARIABLE(x) (unsigned int)(x)->b1.a1, (unsigned int)(x)->b1.a2, \
(unsigned int)(x)->b1.a3, (unsigned int)(x)->b1.a4, \
*(unsigned int*)(unsigned char*)&(x)->b1.a5, \
*(unsigned int*)(((unsigned char*)&(x)->b1.a5) + 4), (unsigned int)(x)->b2

int test(void)
{
struct s2 c;
struct s2 d = {};
struct s2 e = {{}, };
struct s2 f = {{0, 0, 0, 0, 0.0}, 0};
printf("local: struct s2 c: "FORMAT"\n", VARIABLE(&c));
printf("local: struct s2 d = {}: "FORMAT"\n", VARIABLE(&d));
printf("local: struct s2 e = {{}, }: "FORMAT"\n", VARIABLE(&e));
printf("local: struct s2 f = {{0, 0, 0, 0, 0.0}, 0}: "FORMAT"\n", VARIABLE(&f));
printf("global: struct s2 s: "FORMAT"\n", VARIABLE(&s));

return 0;
}

int main()
{
return test();
}


linux+gcc编译没有任何错误或者警告, 程序输出结果:
local: struct s2 c: 00000000 00 bff7d8af 080482e0 0023eff4080498c0, bff7d648
local: struct s2 d = {}: 00000000 00 00000000 00000000 0000000000000000, 00000000
local: struct s2 e = {{}, }: 00000000 00 00000000 00000000 0000000000000000, 00000000
local: struct s2 f = {{0, 0, 0, 0, 0.0}, 0}: 00000000 00 00000000 00000000 0000000000000000, 00000000
global: struct s2 s: 00000000 00 00000000 00000000 0000000000000000, 00000000


visual c++ 6.0编译两个错误, 提示如下:
--------------------Configuration: a - Win32 Debug--------------------
Compiling...
a.c
c:\documents and settings\iceway.zhang\desktop\new folder\a.c(29) : error C2059: syntax error : '}'
c:\documents and settings\iceway.zhang\desktop\new folder\a.c(30) : error C2059: syntax error : '}'
Error executing cl.exe.

a.exe - 2 error(s), 0 warning(s)



C语言局部变量没有初始化经常会导致很多问题, 刚开始学C语言时我总觉得这些变量如果我不
主动赋值, 都是0, 后来才知道对局部非静态变量初始值是未知的.
以前我只知道结构体变量初始化时可以使用struct s2 f = {{0, 0, 0, 0, 0.0}, 0}这种方式,
最近看一个代码时发现有struct s2 d = {}的用法, 因为之前没看过, 也没用过这种方式, 所以
写代码测试, 结果如上所述.

请问, gcc下能通过这只是gcc的特性吗? 另外这种只用一对空花括号初始化的结构体变量能否保证
结构体的成员变量都是0(包括嵌套的结构体)?
对于其他的编译器, 我没有试过, 不知道以上在linux下的测试是否只是偶然现象.

google了很多结果都是说我之前知道的方式(即变量f的初始化), 只是这种方式太过麻烦, 我想
知道一对空的花括号到底有什么作用? 烦请各位指教, 谢谢!!!
...全文
3203 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
selooloo 2009-11-02
  • 打赏
  • 举报
回复
空{},相当于都有元素都是未初始化元素,所以都有元素都被赋值为0,结构体中的局部变量也不例外
比如 struct A{
int a;
int *b;
} x={};
相当于x={0,0}
这里struct s2 d = {};
d.b1.a1,d.b1.a2,d.b1.a3,d.b1.a4,d.b1.a5 d.b2都被赋值为0;
但d.b2->a1等是未知数据,因为还没分配内存,所以不能初始化
selooloo 2009-11-02
  • 打赏
  • 举报
回复
比如 int arr[6]={0,0,0,0,0,21}; //传统语法
int arr[6]={[5]=21};//把arr[5]初始化为21,C99新特性,相对于arr[5],arr[1],arr[2]等都是未初始化元素,都被置0;效果和上面一样
具体可以查阅c99规则;

memcpy是查看内存的方法之一,当然还有别的方法,直接printf也可以;memcpy不但可以看到值还可以看到内存大小的区别;
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 selooloo 的回复:]
按C99指定初始化新特性,未初始化的元素都被置为0;
空的{}应该是所有元素都被置为0,效果和memset(&s, 0, sizeof(struct s2));一样

LZ可以memcpy看一下

[/Quote]

请问你说的未初始化的元素都被置为0, 这个未初始化的元素有什么限定吗?
可是函数中的局部变量未初始化内容都是随机的垃圾数据.

你说的空{}应该是所有元素都被置为0, 我帖子中的代码输出结果是这样的, 我想问问这个特性是在哪里说明的, 具体的空{}初始化都做了什么, 为什么使用空{}可以将结构体初始化成全0?

PS: 你说的memcpy看一下是什么意思?
如果是说用{}初始化后memcpy看看内存, 那么我的代码中数据结果就可以了, 不用再memcpy了.
iceway 2009-11-02
  • 打赏
  • 举报
回复
写错了, 是变量, 不是函数...


我想这个段所说的问题是c代码中变量定义的位置问题, 我记得以前c编译时变量的定义应该写在函数开始部分, 中间的变量定义如果不放在一个新的代码块中就会出错, 不过后来的c99标准允许使用时定义变量...
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 akirya 的回复:]
引用 14 楼 iceway 的回复:

谢谢, 请问这个5.23是什么意思, info gcc显示的帮助我不知道怎么找到你说的5.23?

运行info gcc
然后ctrl+s 输入5.23
[/Quote]

我在另一个系统上找到了:
5.23 Mixed Declarations and Code
================================

ISO C99 and ISO C++ allow declarations and code to be freely mixed
within compound statements. As an extension, GCC also allows this in
C89 mode. For example, you could do:

int i;
/* ... */
i++;
int j = i + 2;

Each identifier is visible from where it is declared until the end of
the enclosing block.

抱歉, 这段说的不是我问的问题.
我想这个段所说的问题是c代码中变量定义的位置问题, 我记得以前c编译时变量的定义应该写在函数开始部分, 中间的函数定义如果不放在一个新的代码块中就会出错, 不过后来的c99标准允许使用时定义变量...

这个不是我要问的问题, 不过还是谢谢你的热心!!!
selooloo 2009-11-02
  • 打赏
  • 举报
回复
按C99指定初始化新特性,未初始化的元素都被置为0;
空的{}应该是所有元素都被置为0,效果和memset(&s, 0, sizeof(struct s2));一样

LZ可以memcpy看一下
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 akirya 的回复:]
引用 14 楼 iceway 的回复:

谢谢, 请问这个5.23是什么意思, info gcc显示的帮助我不知道怎么找到你说的5.23?

运行info gcc
然后ctrl+s 输入5.23
[/Quote]

非常抱歉, 我输入5.23 search不到, 能不能麻烦你把你电脑上的说明段落复制上来吗, 谢谢!

不知道是不是我的gcc没有装完全, 你说的手册部分我找不到...
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 iceway 的回复:]

谢谢, 请问这个5.23是什么意思, info gcc显示的帮助我不知道怎么找到你说的5.23?
[/Quote]
运行info gcc
然后ctrl+s 输入5.23
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 akirya 的回复:]
引用 2 楼 iceway 的回复:
引用 1 楼 akirya 的回复:
gcc作的扩展吧

  一般用{0}; 这样


使用{0}的话, 对于嵌套结构体会提示有警告, 缺少花括号.
如果要消除该警告就要用我以前所知的方式, 那样对于复杂的结构体岂不是非常麻烦?

再者, 如果是gcc的扩展, 那么请问扩展结果是什么, 怎么看到, 谢谢!

info gcc
5.23
[/Quote]


谢谢, 请问这个5.23是什么意思, info gcc显示的帮助我不知道怎么找到你说的5.23?
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 butwang 的回复:]
看规范吧8.5.1  Aggregates  [dcl.init.aggr]
8 An initializer for an aggregate member that is an  empty  class  shall
  have the form of an empty initializer-list {}.  [Example:
          struct S { };
          struct A {
                  S s;
                  int i;
          } a = { { } , 3 };
    --end  example]An empty initializer-list can be used to initialize
  any aggregate. If the aggregate is not an empty class, then each mem-
  ber of the aggregate shall be initialized with a value of the form T()
  (_expr.type.conv_), where T represents the type of  the  uninitialized
  member.

[/Quote]

这位朋友, 谢谢你, 不过我的标题已经说明了, 我想问的是c语言的, 而不是C++.
iceway 2009-11-02
  • 打赏
  • 举报
回复
非常感谢各位的回答, 楼上有朋友说的memset, 我在实际中也是这么用的, 就是因为我以前认为用{}不能初始化一个嵌套的结构体, 所以我都是用memset的.

现在问题是我看到有源代码使用{}来初始化一个嵌套的结构体, 我想问问一个空的花括号在初始化结构体时到底表示什么?

还是用我的示例中的结构为例:
struct s1
{
int a1;
char a2;
char *a3;
long unsigned int a4;
double a5;
};

struct s2
{
struct s1 b1;
struct s2 *b2;
};

struct s2 a = {} 和struct s2 a = {{}, NULL}两种初始化的结果有什么区别, 按照我以前的理解, 只有第二种方式才是对的, 可是现在在gcc下使用第一种方式也可以, 而且结果正确, 所以我想弄明白怎么回事.

请各位给我说说一个空的花括号初始化结构体到底是做了什么, 这个{}代表了什么, 一段纯粹的0x00的内存区还是其他?

memset暂时请不要考虑, 谢谢!!!
iceway 2009-11-02
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 selooloo 的回复:]
空{},相当于都有元素都是未初始化元素,所以都有元素都被赋值为0,结构体中的局部变量也不例外
比如 struct A{
  int a;
  int *b;
} x={};
相当于x={0,0}
这里struct s2 d = {};
d.b1.a1,d.b1.a2,d.b1.a3,d.b1.a4,d.b1.a5 d.b2都被赋值为0;
但d.b2->a1等是未知数据,因为还没分配内存,所以不能初始化

[/Quote]

谢谢了, 我想问的就是这个, 我等会找找C99的规则看看...

butwang 2009-10-30
  • 打赏
  • 举报
回复
是C++的,
VC上试了C语言的 的确不行
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 butwang 的回复:]
看规范吧8.5.1  Aggregates  [dcl.init.aggr]
8 An initializer for an aggregate member that is an  empty  class  shall
  have the form of an empty initializer-list {}.  [Example:
          struct S { };
          struct A {
                  S s;
                  int i;
          } a = { { } , 3 };
    --end  example]An empty initializer-list can be used to initialize
  any aggregate. If the aggregate is not an empty class, then each mem-
  ber of the aggregate shall be initialized with a value of the form T()
  (_expr.type.conv_), where T represents the type of  the  uninitialized
  member.

[/Quote]
这是C++的吧

VS2008的C编译器确实不允许空的初始化列表。
liangyonglou 2009-10-30
  • 打赏
  • 举报
回复
建议使用memset函数初始化,简单,方便。
butwang 2009-10-30
  • 打赏
  • 举报
回复
看规范吧8.5.1 Aggregates [dcl.init.aggr]
8 An initializer for an aggregate member that is an empty class shall
have the form of an empty initializer-list {}. [Example:
struct S { };
struct A {
S s;
int i;
} a = { { } , 3 };
--end example] An empty initializer-list can be used to initialize
any aggregate.
If the aggregate is not an empty class, then each mem-
ber of the aggregate shall be initialized with a value of the form T()
(_expr.type.conv_), where T represents the type of the uninitialized
member.
taodm 2009-10-30
  • 打赏
  • 举报
回复
建议楼主装VC2005、VC2008再试。VC6的结果一概无试。
thy38 2009-10-30
  • 打赏
  • 举报
回复
最好还是用可移植性高的做法。
hly930 2009-10-30
  • 打赏
  • 举报
回复
用memset函数初始化
xkyx_cn 2009-10-30
  • 打赏
  • 举报
回复
工作当中一般这样写:

struct s2 s;
memset(&s, 0, sizeof(struct s2));
加载更多回复(3)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧