zoukankan      html  css  js  c++  java
  • 一种KEIL中定义过的变量在使用中提示未定义的情况

    【环境】

      > KEIL5.25

      > win10

      > @2018-4-23 

    【问题】

    头文件互包含导致的错误(使用了另一文件的类型定义)

    文件<fileA.h>

     1 <fileA.h>
     2 
     3 #ifndef    __FILEA_H__
     4 #define    __FILEA_H__
     5 
     6 #include "fileB.h"
     7 
     8 typedef struct
     9 {
    10     int var;
    11 }stuct_A_s;
    12 
    13 
    14 #endif

    文件<fileB.h>

     1 <fileB.h>
     2 
     3 #ifndef    __FILEB_H__
     4 #define    __FILEB_H__
     5  
     6 #include "fileA.h"
     7 
     8 typedef struct
     9 {
    10     int var;
    11     struct_A_s obj;
    12 }struct_B_s;
    13 
    14 #endif

    编译后报错:在文件<fileB.h>中   error:  #20: identifier "struct_A_s" is undefined  

    【分析】

    导致上述错误的原因,是在文件<fileA.h>中,使用了 fileB.h,而文件<fileB.h>中使用的类  struct_A_s 在其定义之前,故产生了先使用后定义的语法错误

    具体分析:

      从文件<fileA.h>开始分析:

      > 执行避免头文件重复包含的宏 --- <fileA.h>

      > 包含文件<fileB.h>,进入文件<fileB.h>

      > 执行避免头文件重复包含的宏 --- <fileB.h>

      > 包含文件<fileA.h>,进入文件<fileA.h>

      > 由于避免重复包含宏的控制,进不去A文件内容部分,跳转回文件<fileB.h>

      > 执行结构体 struct_B_s 定义,结构体成员类型使用了结构体 struct_A_s ,这就出现了使用了未定义的情况,执行完毕跳转回文件<fileA.h>

      > 执行结构体 struct_A_s 定义,结合上一步就发生了先使用后定义的问题,执行完毕结束

      结论:编译器先从文件<fileA.h>开始编译就会出现本文所示错误

      从文件<fileB.h>开始分析:

      > 执行避免头文件重复包含的宏 --- <fileB.h>

      > 包含文件<fileA.h>,进入文件<fileA.h>

      > 执行避免头文件重复包含的宏 --- <fileA.h>

      > 包含文件<fileB.h>,进入文件<fileB.h>

      > 由于避免重复包含宏的控制,进不去B文件内容部分,跳转回文件<fileA.h>

      > 执行结构体 struct_A_s 定义,执行完毕跳转回文件<fileB.h>

      > 执行结构体 struct_B_s 定义,执行完毕结束

      结论:编译器先从文件<fileB.h>开始编译就不会报错误

    【解决】

      # 去除文件<fileA.h>中包含文件<fileB.h>的语句部分,可解决此问题

      # 由于分析推出是编译顺序导致错误的出现,特做了一下一些事做实验:

        > 控制文件 <fileA.h> 与 <fileB.h> 的编译顺序  (做了文件名的更改,即按照字母表顺序修改文件名达到两次编译时两个文件的排序相异)

        > 两次编译的结果都是报相同的错误,error:  #20: identifier "struct_A_s" is undefined  

    【结论】

      # 综上暂推出,编译器在编译时,每个文件都会单独编译一遍,所以不论文件 <fileA.h> 与 <fileB.h> 的排序,都会出现相同的问题

      # 一般是杜绝文件互相包含的,因为文件包含的意义就是要使用被包含文件的一些定义,互相包含就会出现先使用后定义 的情况发生

      # 了解一些编译原理的知识后,将会得到更权威的解惑,以上只是根据现象分析的结果

  • 相关阅读:
    gateway dblink transport mssql image datatype to oracle blob datatype
    Sql server 数据库备份、恢复等
    sql full left right inner cross 基础
    真的发现自己已不再年轻
    利用日志备份恢复时,提示 该 LSN 太晚,无法应用到数据库
    系统调用原理(转)
    Linux添加自定义系统调用
    libusb 介绍
    用户空间与内核空间数据交换的方式(4)relayfs
    用户空间与内核空间数据交换的方式(2)procfs
  • 原文地址:https://www.cnblogs.com/skullboyer/p/8891579.html
Copyright © 2011-2022 走看看