奇怪的C程序

5
请检查以下代码片段。
struct st
{
    struct st
    {
        int a ;
        int b ;
    } st;

    int a1 ;
} ;

struct st obj ;
struct st obj1 ;

int main()
{
    return obj.a1 + obj1.b ;
}

微软的编译器Visual Studio 6.0成功地编译了程序。我对“struct st”的使用感到困惑。obj和obj1的大小是多少?


1
哪个结构体是 st?这里有四个。 - Naveen
无论 printf("%d %d\n", sizeof(obj), sizeof(obj1)); 返回什么... - Erich Kitzmueller
你发布的内容在我所记得的任何标准中都不是有效的C语言。已重新标记。 - Tim Post
下次提问时,请说明您使用的平台和编译器。您发布的代码能够成功编译,这正说明了我们需要这样的澄清信息 :) - Tim Post
你这个调试大师! :) 当我第一次看到它工作时,我很兴奋。 - Ganesh Gopalasubramanian
1
在我试过所有的编译器都无法编译成功后,我只能引用塔可钟犬的名言:“噢哦,我想我需要一个更大的盒子”。 - Tim Post
4个回答

8

GCC报错:

错误:重复定义嵌套的‘struct st’
错误:‘struct st’没有名为‘a1’的成员

如果VC6可以编译通过,那么这是无效的。

如果您想知道obj的大小,可以使用sizeof obj。我会假设VC6将结构展开并分配了三个整数。


1
顺便提一下,VC9会出现错误:错误C3769:'st':嵌套类不能与直接封闭类具有相同的名称。 - Naveen
@jleedev说:我猜MSVC确实将其展平了 - obj1.st.st.st.st.a = 10将影响到obj1.a - Jacob
顺便问一下,什么是正确的?编译器应该发出错误还是应该成功编译程序? - Ganesh Gopalasubramanian
6
编译器此时应该在咒骂你。 - Tim Post
@Tinkertim 编译器!!我听说有一个“比尔”在某个“门口”通过了! - Ganesh Gopalasubramanian
VC9也成功编译了它!我使用的版本是“Microsoft(R)32位C / C ++优化编译器版本15.00.30729.01 for 80x86”。 - Ganesh Gopalasubramanian

1

obj和obj1的大小相同。由于两者都没有初始化,obj.a1 + obj1.b的值未定义,而且你的代码编译器都有问题。如果它实际上构建了,那么一切都无法预测。

NB:

那段代码得到了编译器的很多“帮助”才能正常工作。所谓“帮助”,就是“我们必须在截止日期前发布它……现在是漏洞分类时间,特别是在解析器方面!”


不能说它们没有被初始化。在C语言中,“全局”对象总是被零初始化。当然,这一切都无关紧要,因为代码无法编译。 - AnT stands with Russia
@AndreyT:如果那真的编译通过了,我想我们可以抛弃任何关于作用域如何处理事物的标准遗留问题了吧? - Tim Post
@AndreyT:如果解析器那么容易混淆……还有什么是可靠的?我的回答试图反映这一点,而不会激怒VS的粉丝们。 - Tim Post

1

仅仅快速浏览一下,我认为您已经定义了一个结构体,并声明了两个类型为结构体的变量。因此,obj和obj1的sizeof应该相同,因为它们都是st类型!不用说,具有相同名称的嵌套结构是非法的!而且很惊讶它竟然编译通过了。但请记住,自VC 6发布以来,C语言已经发生了变化(如果我没记错的话)。


VS6发布之前C99并未获得认证,但这并不是编译无效代码的原因,因为自那以后的任何版本的VS都没有声称实现C99。我相信问题只是因为VS6不被称为“严谨”的C编译器... - Steve Jessop

0

这不是有效的C代码。在C语言中没有“类作用域”,从C语言的角度来看,struct st的两个定义都定义了相同的类型两次。这是非法的。

这只有作为C++代码才是良好的形式,但除此之外,程序只是计算并返回0。为什么要跳过所有这些障碍来返回0,我不知道。该程序在C++中也是不良形式的。将类st声明为类st的成员(即使用相同的名称)是非法的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接