问题

我曾经很困惑,就是在两个编译单元当中,如何把一个单元中声明的struct结构引入到另外一个单元中来,折腾了很久,后来发现这位大神的留言

不是这么用的……

类型的定义和类型变量的定义不同,
类型定义只是描述一个类型,
是给编译器看的,
不会产生可执行代码。
变量定义是指在执行文件中真实得存在这么一块内容。

因为每个.c里都要写清楚类型定义很麻烦,
所以一般都把类型定义写在.h里
,而在.c里采用简单的写法,如struct A a;
这样定义变量,
不需把整个类型的描述再写一遍。

--------------------------------
所以,struct类型定义放到 ser.h里面,
ser.cpp 里加struct str st_r;
CmfcDlg.cpp加上#include "ser.h"
然后直接使用extern struct str st_r;

--------------------------------
楼主要有研究精神……
你先试下我上面说的……

我顿时发现自己是有多么的傻x.

说白了extern面向结构的语法,只针对对象的本身,而不包括结构,结构只是一个模板,是写给编译器看得。并不存在extern结构的说法,只能extern结构对象。

如果需要在两个编译单元内引入外部变量,那么你必须在两个文件当中引入这个结构,才能使用。

最科学的方法就是把结构写进一个.h文件,然后把它各自#include进每一个需要用到这个结构的文件当中。

示例,在a.c中声明结构chicken,随后声明一个叫jason的chicken对象。把jason引入b.c

a.c

struct chicken
{
char name[];
int age;
}; struct chicken jason = {
"jason",
};

b.c

#include <stdio.h>
struct chicken
{
char name[];
int age;
}; extern struct chicken jason; int main(void)
{
printf("%s\n", jason.name);//输出jason
}

这个例子有一个不合理的地方,就是两个文件都需要在各自上下文中声明结构chicken,一旦结构chicken有所改动,就会相当麻烦,你需要修改所有包含了该结构的页面。

所以这种情况下,通常会采取把结构声明语句挪出来独立作为一个头文件,之后用到的地方各自引用该头文件,下面是改动过的示例。

结构chicken被单独至于这个chicken.h文件当中:

struct chicken
{
char name[];
int age;
};

a.c:

#include "chicken.h"

struct chicken jason = {
"jason Chao",
};

b.c:

#include <stdio.h>
#include "chicken.h" //extern struct chicken jason;
struct chicken jason; int main(void)
{
printf("%s\n", jason.name);
}

结果是b.c会正常输出jason.name.

题外话

1.其实extern关键字是c的标识符声明中的[存储类修饰符]的一员,[存储类修饰符]包括extern、static、auto、register,在声明变量、函数、结构化数据时,extern标识符是默认的,也就是说,上面的例子即使不手动指明extern关键字,编译器也会默认把它当成extern关键字处理.

a.c

struct chicken
{
char name[];
int age;
}; struct chicken jason = {
"jason",
};

b.c

#include <stdio.h>
struct chicken
{
char name[];
int age;
}; struct chicken jason;//等价于extern struct chicken jason; int main(void)
{
printf("%s\n", jason.name);//输出jason
}

2.注意哦,变量只能初始化(赋予变量字面值)一次,就算外部变量也是一样哦,不然编译器会提示multiple definition of `xxx'

[C]关于extern与struct的更多相关文章

  1. 编译binutil包报错 error: array type has incomplete element type extern const struct relax_type md_relax_table[];

    安装lfs时编译binutils出错: ../../sources/binutils-2.15.91.0.2/gas/config/tc-i386.h:457:32: error: array typ ...

  2. C++extern关键字理解

    extern是一种"外部声明"的关键字,字面意思就是在此处声明某种变量或函数,在外部定义. 下面的示意图是我的理解. extern关键字的主要作用是扩大变量/函数的作用域,使得其它 ...

  3. php内核分析(二)-ZTS和zend_try

    这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux ZTS 我们会看到文章中有很多地方是: #ifdef ZTS # define CG(v) ZEND_TSRMG(comp ...

  4. C++学习笔记 知识集锦(二)

    1. 命名规范 2. 代码格式 3. QString的判断 4. 对象的判空 5. 隐式接口&显式接口 6. vector&string 7. static 8. const 9. v ...

  5. Android Bootloader LittleKernel的两篇文章 【转】

    转自:http://blog.csdn.net/loongembedded/article/details/41747523 2014-12-05 14:37 3599人阅读 评论(2) 收藏 举报 ...

  6. Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  7. linux kernel i2c底层代码跟踪

    其实跟上次跟的平台总线有关 在arch/arm/mach-mx6/board-mx6q_sabresd.c 文件中 static void __init mx6_sabresd_board_init( ...

  8. libevent源码分析(一)

    分析libevent的源代码,我的想法的是先分析各种结构体,struct event_base.struct event,然后是event_base_new函数.event_new函数.event_a ...

  9. Linux内核启动logo

    之前在分析samsung的fb驱动代码的时候,其中有一段代码是处理内核logo显示相关的,今天就内核logo这个话题来聊一聊! 一.处理内核logo显示相关的代码在哪? 回到samsung的fb驱动代 ...

随机推荐

  1. 修改xshell的默认字间距和行间距

    可能是不小心修改了xshell的某个配置,导致打开的会话中显示字间距和行间距都非常大,严重影响工作.参照官方手册也不能修改正常,详见:http://www.xshellcn.com/wenti/xiu ...

  2. C#利用Guid实现真随机数

    C#中的随机数可以利用Random类很简单地生成随机数,代码如下: Random rdmNum=new Random();//生成随机数对象 int ans=rdmNum.Next(a,b);//生成 ...

  3. 开源框架.netCore DncZeus学习(二)配置连接

    配置连接字符串,update-database,初始数据后,访问报错,提示offset错误.因为本机上使用的sql2008. .net Core 2.X中的EF访问sqlserver2008默认使用的 ...

  4. C# web IIS服务器 DateTime 带中文解决

    C# Web应用在某些电脑IIS上部署运行,读取当前时间带有中文,比如2018-5-1 星期一 上午 12:00:00,虽然使用Format转换可以解决,但代码量较大难免遗漏,会引发问题,为了解决该问 ...

  5. luogu 1966 火柴排队 离散化+逆序对

    题意:找到最小改变对数使a数组的第i大和b数组的第i大相等 则先将a,b,数组编号再排序,则数组显示的就是排名第i的数的编号 再关键一步:c[a[i].id]=b[i].id 实质上就是新建一个数组, ...

  6. 面向对象 ( OO ) 的程序设计——创建对象

    本文地址:http://www.cnblogs.com/veinyin/p/7608000.html  为了避免大量重复代码产生,可采用以下方法创建对象 1 工厂模式 function createP ...

  7. linux 测试 get 请求 跳过SSL证书验证

    Linux 下测试 get 请求: curl : curl "http://www.qq.com" # 标准输出页面内容 curl -i "http://www.qq.c ...

  8. linux下搭建lamp环境以及安装swoole扩展

    linux下搭建lamp环境以及安装swoole扩展   一.CentOS 6.5使用yum快速搭建LAMP环境 准备工作:先更新一下yum源  我安装的环境是:apache2.2.15+mysql5 ...

  9. Kafka如何保证消息不丢失不重复

    首先需要思考下边几个问题: 消息丢失是什么造成的,从生产端和消费端两个角度来考虑 消息重复是什么造成的,从生产端和消费端两个角度来考虑 如何保证消息有序 如果保证消息不重不漏,损失的是什么 大概总结下 ...

  10. RSA加解密-2

    Java使用RSA加密解密签名及校验   package com.ihep; import java.io.BufferedReader; import java.io.BufferedWriter; ...