hrefspace

 找回密码
 立即注册
搜索
热搜: PHP PS 程序设计
查看: 630|回复: 9

奇特的编译 error: C2016

[复制链接]

493

主题

493

帖子

1509

积分

大司空

Rank: 5Rank: 5

积分
1509
发表于 2024-2-17 08:24:30 | 显示全部楼层 |阅读模式
我正在搭建全新的HugeCalc架构,尝试采用mathe曾给出的建议
但编译时遇到一条提示 error C2016: C requires that a struct or union has at least one member

为了分析问题,我写了个简单的测试程序:
  1. 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++既然允许,是什么原因呢?
回复

使用道具 举报

8

主题

204

帖子

44

积分

新手上路

Rank: 1

积分
44
发表于 2024-2-17 08:25:18 | 显示全部楼层
C++编译时,应该是会将所有的class,struct都统一为一种C++对象模型。对编译器而言,在语义上,class 和 struct是等价的。
而C++允许定义空类,每个类对象都起码占一个字节(不考虑内存对齐)。
具体的,《Inside The C++ Object Model》讲过。
回复

使用道具 举报

0

主题

168

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2024-2-17 08:26:03 | 显示全部楼层
是的,C不允许空对象,但是C++由于支持模板类等,经常广泛使用空对象。
不过LZ可以试着直接使用:
typedef struct _HI       *PHI;
也就是不定义_HI而直接使用其指针。
回复

使用道具 举报

0

主题

202

帖子

49

积分

新手上路

Rank: 1

积分
49
发表于 2024-2-17 08:26:48 | 显示全部楼层
2# medie2005

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

不知上述观点是否正确?
回复

使用道具 举报

0

主题

202

帖子

49

积分

新手上路

Rank: 1

积分
49
发表于 2024-2-17 08:27:21 | 显示全部楼层
不正确。 编译器是通过类名来区分是否是同一个类的指针。
回复

使用道具 举报

0

主题

208

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2024-2-17 08:27:34 | 显示全部楼层
3# mathe

mathe 就是高,很快就想到了变通手法。
  1. 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'
应该说基本达到提醒警告的目的了。
回复

使用道具 举报

0

主题

190

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2024-2-17 08:28:08 | 显示全部楼层
不正确。 编译器是通过类名来区分是否是同一个类的指针。
mathe 发表于 2010-3-18 08:29

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

0

主题

199

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2024-2-17 08:28:44 | 显示全部楼层
C++允许定义空对象,也就是必须允许定义空类。
但一个空类,可以实例化为多个空对象,如何区分这些空对象?
比如class A是空类,定义A  test1, test2。
在编译器角度,如何区分test1和test2?
起码,每个空对象都要占用内存空间,以区别于其他空对象。
回复

使用道具 举报

0

主题

186

帖子

163

积分

关内侯

Rank: 2

积分
163
发表于 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)
来调用这个函数。
回复

使用道具 举报

565

主题

744

帖子

1942

积分

大司空

Rank: 5Rank: 5

积分
1942
发表于 2024-2-17 08:29:54 | 显示全部楼层
既然“C中就是用结构名来区分两个不同的结构的”,
那究竟是什么原因必须规定“C requires that a struct or union has at least one member”?

我的意思是:在主题帖的定义下,我们人感觉是合理的,为什么编译器会拒绝呢?根本原因是什么呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|hrefspace

GMT+8, 2024-5-4 21:14 , Processed in 0.078872 second(s), 22 queries .

Powered by hrefspace X3.4 Licensed

Copyright © 2022, hrefspace.

快速回复 返回顶部 返回列表