123456789 发表于 2024-2-17 08:24:30

奇特的编译 error: C2016

我正在搭建全新的HugeCalc架构,尝试采用mathe曾给出的建议。
但编译时遇到一条提示 error C2016: C requires that a struct or union has at least one member

为了分析问题,我写了个简单的测试程序:typedef struct _HI{}      *PHI;int main(void){      int i;      PHI p;      p = (PHI)&i;      return 0;}如果存成 test.cpp,在 VC2008 及 VC6 下均顺利编译通过。

但若修改文件名为 test.c,在VC6 下提示:Deleting intermediate files and output files for project 'test - Win32 Debug'.
--------------------Configuration: test - Win32 Debug--------------------
Compiling...
test.c
e:\jason\test\test.c(1) : error C2059: syntax error : '}'
e:\jason\test\test.c(6) : error C2065: 'PHI' : undeclared identifier
e:\jason\test\test.c(6) : error C2146: syntax error : missing ';' before identifier 'p'
e:\jason\test\test.c(6) : error C2065: 'p' : undeclared identifier
Error executing cl.exe.

test.exe - 4 error(s), 0 warning(s)

在VC2008下提示:------ Rebuild All started: Project: test, Configuration: Debug Win32 ------
Deleting intermediate and output files for project 'test', configuration 'Debug|Win32'
Compiling...
test.c
e:\jason\test\test.c(1) : error C2016: C requires that a struct or union has at least one member
Build log was saved at "file://e:\Jason\test\Debug\BuildLog.htm"
test - 1 error(s), 0 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

我想问的是:为什么C中不允许定义空的结构体?而C++既然允许,是什么原因呢?

渐行渐远 发表于 2024-2-17 08:25:18

C++编译时,应该是会将所有的class,struct都统一为一种C++对象模型。对编译器而言,在语义上,class 和 struct是等价的。
而C++允许定义空类,每个类对象都起码占一个字节(不考虑内存对齐)。
具体的,《Inside The C++ Object Model》讲过。

ebirugerxos 发表于 2024-2-17 08:26:03

是的,C不允许空对象,但是C++由于支持模板类等,经常广泛使用空对象。
不过LZ可以试着直接使用:
typedef struct _HI       *PHI;
也就是不定义_HI而直接使用其指针。

isotaztiqotew 发表于 2024-2-17 08:26:48

2# medie2005

看了你的说明,
我突然想到在 C++ 里,class 里会隐藏一个指针,用来记录成员函数地址,或者是虚拟函数表的索引号。
因为不同的class其成员函数地址肯定不一样,正是有因为这个隐藏的变量,可以让编译器进行区分。
而C中不存在上述机制,所以编译器无法进行空结构的区分。

不知上述观点是否正确?

isotaztiqotew 发表于 2024-2-17 08:27:21

不正确。 编译器是通过类名来区分是否是同一个类的指针。

akomosuse 发表于 2024-2-17 08:27:34

3# mathe

mathe 就是高,很快就想到了变通手法。typedef struct _HI      *PHI;typedef struct _HX      *PHX;PHI HI_New( void );PHX HX_New( void );void HI_Del( PHI pHI );void HX_Del( PHX pHX );如果混用了 PHI/PHX 类型,比如:HX_Del( HI_New() );
则编译时不会报error,但会报 warning C4133: 'function' : incompatible types - from 'PHI' to 'PHX'
应该说基本达到提醒警告的目的了。

uucepekoqijew 发表于 2024-2-17 08:28:08

不正确。 编译器是通过类名来区分是否是同一个类的指针。
mathe 发表于 2010-3-18 08:29 http://bbs.emath.ac.cn/images/common/back.gif

那为什么C中不可以以结构名进行区分呢?

saluozu 发表于 2024-2-17 08:28:44

C++允许定义空对象,也就是必须允许定义空类。
但一个空类,可以实例化为多个空对象,如何区分这些空对象?
比如class A是空类,定义Atest1, test2。
在编译器角度,如何区分test1和test2?
起码,每个空对象都要占用内存空间,以区别于其他空对象。

azanuvahejih 发表于 2024-2-17 08:29:08

C中就是用结构名来区分两个不同的结构的。
所以
HX_Del( HI_New() );
会报告警告,应为这时不同类型之间指针的转化(结构名不同)。
对于C++中的空对象,不会产生真正的内存空间的消耗,或者我们可以赋予任意内存地址空间。具有意义的只有其逻辑值。对于同一个空对象的两个不同实例,通过地址区分它们没有意义。
而C++中的空类主要用于模板类,比如我们可以如下定义一个functor
class compare{
public:
    bool operator()(int a, int b)const;
};
然后我们可以通过比如
compare c;
c(1,2)
来调用这个函数。

litong 发表于 2024-2-17 08:29:54

既然“C中就是用结构名来区分两个不同的结构的”,
那究竟是什么原因必须规定“C requires that a struct or union has at least one member”?

我的意思是:在主题帖的定义下,我们人感觉是合理的,为什么编译器会拒绝呢?根本原因是什么呢?
页: [1]
查看完整版本: 奇特的编译 error: C2016