sizeof输出引出对C语言定义变量后的初始化的理解

astone2007 发布于 2013/08/08 10:50
阅读 1K+
收藏 0
GCC

看看下面这段代码的输出,希望大家分析一下原因。

#include<stdio.h>
int main()
{
        char last[6]={{1},{2},{3},{4},{5},{6},{7}};
        printf("The size is:%d\n",sizeof(last));
        return 0;
}
我编译时会出现如此警告:

simon@simon-Presario:~/heps/CWork$ gcc -Wall sizeofchar.c -o sizeofchar
sizeofchar.c: In function ‘main’:
sizeofchar.c:4:2: warning: braces around scalar initializer [enabled by default]
sizeofchar.c:4:2: warning: (near initialization for ‘last[0]’) [enabled by default]
sizeofchar.c:4:2: warning: braces around scalar initializer [enabled by default]
sizeofchar.c:4:2: warning: (near initialization for ‘last[1]’) [enabled by default]

……

{{1},{2},{3},{4},{5},{6},{7}};
这种形式理解为数组还是结构体?对于last[6]会什么是警告而不是报错?(gcc编译)

加载中
0
L5_Railgun
L5_Railgun

没看懂你用的啥编译器,反正我是没觉得能编译过,在VS一跑,直接C2078

char last[6]={{1},{2},{3},{4},{5},{6},{7}};
其实等价于
char last[6][1]={{1},{2},{3},{4},{5},{6},{7}};

编译器都会告诉你初始值过多。如果全优化生成后,main函数的堆栈其实会是

0x1000 RET ADDR
0x0FFC EBP
0x0FFB ... <- last[5]
0x0FF6 ....<- last[0]
如果第七个元素可以被赋值,那会赋值到哪里去? 如果EBP被篡改了,那会出现什么情况?

L5_Railgun
L5_Railgun
回复 @2007robot : 没用过GCC,不过听说很多GCC能通过的奇葩代码在MS Complier就无法编译通过。比如说这里,如果GCC将last视为结构体,然后默认8字节对齐,然后你懂的,自然是可以通过的,当然GCC如果这么做,其实已经违背了“等价编译”的原则。 这种编译器间的奇葩差异 @中山野鬼 也许知道
astone2007
astone2007
用gcc编译的,我也很纳闷最后一个元素放在哪儿了?
0
中山野鬼
中山野鬼
warning可以设置为就是错嘛。哈。sizeof (last)肯定是6,这个跑不掉。因为我记得c标准有段要求,sizeof(array) / sizeof(array[0]) 要为数组的个数。你那种赋值gcc会给出警告。赋值方式错误。如果是{1,2,3,4,5,6,7},则会警告超过超过范围。还是那句,警告可以被设置成就是错误。
0
L5_Railgun
L5_Railgun

引用来自“中山野鬼”的答案

warning可以设置为就是错嘛。哈。sizeof (last)肯定是6,这个跑不掉。因为我记得c标准有段要求,sizeof(array) / sizeof(array[0]) 要为数组的个数。你那种赋值gcc会给出警告。赋值方式错误。如果是{1,2,3,4,5,6,7},则会警告超过超过范围。还是那句,警告可以被设置成就是错误。

这种不应该是warning,而是error,我觉得。

如果能编译,能跑,那么关闭DEP,sub esp,6之后,赋值7必然篡改EBP,然后,就会发现堆栈乱翻天了

0
中山野鬼
中山野鬼

引用来自“艾米”的答案

引用来自“中山野鬼”的答案

warning可以设置为就是错嘛。哈。sizeof (last)肯定是6,这个跑不掉。因为我记得c标准有段要求,sizeof(array) / sizeof(array[0]) 要为数组的个数。你那种赋值gcc会给出警告。赋值方式错误。如果是{1,2,3,4,5,6,7},则会警告超过超过范围。还是那句,警告可以被设置成就是错误。

这种不应该是warning,而是error,我觉得。

如果能编译,能跑,那么关闭DEP,sub esp,6之后,赋值7必然篡改EBP,然后,就会发现堆栈乱翻天了

哈,类似这种情况的,多了去了,就是书写直接导致边界溢出但编译器不可能各个都认为是错误。而且数组,只是个明确长度的连续空间而已,编译器给予其分配空间,和向这个地址的空间赋值,是两个事件。
astone2007
astone2007
弄成这样吧: char last[6]={1,2,3,4,5,6};
中山野鬼
中山野鬼
回复 @2007robot : 有空纠结这个,不如和我一样Wall。对所有wanring地方的代码进行修复。
astone2007
astone2007
warning: excess elements in array initializer (数组初始值设定项中有多余元素)[enabled by default] warning: (near initialization for ‘last’) [enabled by default] 这是gcc的警告信息,没想到只是警告,感觉gcc还是把主动权交给程序员本身的一种编译器!
返回顶部
顶部