首页 > C语言 #ifndef 引起的redefinition of xxx 问题解决

C语言 #ifndef 引起的redefinition of xxx 问题解决

问题如下

多个.c和.h文件

其中cloth.h分布被hat.hpaths.h包含,编译时出现如下问题:

error: redefinition of struct _Cloth

我的cloth.h定义如下:

#include 
#include 
#include "retval.h"struct _Cloth;
typedef struct _Cloth Cloth;typedef Cloth* (*createClothFunc)();
typedef void (*deleteClothFunc)(Cloth* thiz);struct _Cloth 
{ createClothFunc createCloth;deleteClothFunc deleteCloth;
};

_Cloth 结构体先声明,再定义,显然满足C语言的语法,那麽以上重复定义的异常来自那里呢?

问题解决

紧接着发现该问题是在编译时检测出来的,那麽分析一下编译器在编译C语言都做了一些什么呢?

  1. 预处理

  2. 编译

  3. 汇编

  4. 链接

详细讲解可以参考C语言编译过程

关于#ifndef 条件编译 的作用如下

#ifndef x //先测试x是否被宏定义过
#define xcode 1    //如果x没有被宏定义过,定义x,并编译code 1#endifcode 2    //如果x已经定义过了则编译程序段2的语句,“忽视”程序段1。

显然其最主要的目的是为了防止头文件 的重复包含和编译。

到此,以上结构体重定义的问题就比较清晰了,cloth.h被重复包含,且因为cloth.h未指定条件编译,被重复编译了。此时编译器会认为cloth.h中的结构体定义是被重复定义得。

在多文件的开发过程种,需要规范化头文件的定义,增加条件编译相关的代码,防止头文件被重复包含导致的编译 异常。

更多相关:

  • PCL1.9.1并没有支持vs2015版本的exe版本,然后需要下载PCL的源码重新自己CMake编译出vs2015版本的编译的目的:1、得到支持vs2015的版本的PCL1.9.1 前期准备1、下载PCL源码:https://github.com/PointCloudLibrary/pcl2、下载安装版(主要是为...

  • 下载gcc文档,第三章有详细的build options的介绍。 最近我用到2个关键的option 来定位问题,简单介绍一下: 1. -E: 只是进行预编译,不会编译和link。用于检查宏在代码中的展开是否符合预期; 2.--verbose: 开启verbose mode, 用于输出编译整个过程中的详细信息,可帮助查看build...

  • 浅谈GCC预编译头技术 文/jorge ——谨以此文,悼念我等待MinGW编译时逝去的那些时间。 其 实刚开始编程的时候,我是丝毫不重视编译速度之类的问题的,原因很简单,因为那时我用BASICA。后来一直用到C++ Builder,尽管Borland的广告无时无刻不在吹嘘其编译速度,我却从没有对这个问题上心过,因为心里根本没有“...

  • 在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓平台,实际上包含两个概念:体系结构(Architecture)、操作系统(Operating System)。同一个体系结构可以运行...

  • 文章目录前言Makefile 编译流程1. 平台变量/环境变量的初始化。2. 编译需要的源码文件变量初始化。3. include 目录的设置。4. 编译的执行逻辑。问题记录1:可能的打包命令`ar` 失效问题5. 执行具体的编译指令问题记录2: jar 包编译...

  • 这里将分享我使用PCL库的遇到的一些坑,以及总结的技巧,当然也需要各位能够多多分享,将公众号的文章或者知识星球的文章转发到朋友圈。 pcl_common中主要是包含了PCL库常用的公共数据结构和方法,比如PointCloud的类和许多用于表示点,曲面,法向量,特征描述等点的类型,用于计算距离,均值以及协方差,角度转换以及几何变化的函...

  • C++中extern是指全局的意思。它一般有两个方面的用途: 1、声明变量 首先说一下声明和定义的区别: ①变量的定义:用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且仅有一个定义。 ②变量的声明:用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过使用extern...

  • 在构造自己的类时,有可能会碰到两个类之间的相互引用问题,例如:定义了类A类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A {     int i;     B b; } class B {     int i;     A* a; } 请注意上面的定义内容,一般情况下是不能出现类A,类B相互引用都定义对象,即...

  •   前天在玩OLED时想完成一直想弄得一个东西,就是简单的单片机游戏。因为STM32和nRF51822的内存足够,所以就用缓存数组的方法来显示图像(我也不知道术语是啥,反正就是在内存中建立一个128X64的二维数组,更新显示时将整个数组刷新到屏幕上),而且这两个OLED是串口的(还有一个128X32的OLED,一样串口的,连驱动时序和...

  • 三、继承中容易引起的错误有时候继承也会带来些错误,比如说下面这条css定义: body{color:blue} 在有些浏览器中这句定义会使除表格之外的文本变成蓝色。从技术上来说,这是不正确的,但是它确实存在。所以我们经常需要借助于某些技巧,比如将css定义成这样: body,table,th,td{color:blue} 这样表格...