问题

我曾经很困惑,就是在两个编译单元当中,如何把一个单元中声明的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. Linux下的解压命令

    Linux下常见的压缩包格式有5种:zip tar.gz tar.bz2 tar.xz tar.Z 其中tar是种打包格式,gz和bz2等后缀才是指代压缩方式:gzip和bzip2 filename. ...

  2. 万能五笔输入法"@相反

    经过查找资料,发现是因为键盘使用的英国导致,改为美国解决,其他输入法没发现这个问题.

  3. STC等单片机一开机就停电模式烧写程序办法

    为了测试一个低功耗程序,程序一开机就进入停机模式,结果刷不回来了,经过两个小时的试验,必须4个线同时插拔vcc,rxd,txd,gnd.如果只断开vcc是不行的.

  4. ****** 四十二 ******、软设笔记【网络基础】-IPv6协议、常用的网络协议

    一.IPv6协议 IPv6协议,全称"互联网协议第6版",即下一代的网际协议. 相对于IPv4来说,IPv6协议主要改进: *扩展的地址.IPv6地址长度为128位. *IPv6使 ...

  5. python 小技巧

    计算时间差,时间加减运算代码 最近在学习数据预处理,碰到日期型数据不会处理,上网查了下: Q:如何方便的计算两个时间的差,如两个时间相差几天,几小时等A:使用datetime模块可以很方便的解决这个问 ...

  6. ArrayList的底层实现

    package zy809; public class myArrayList { /** 存放元素 */ private Object[] data;// 创建一个数组引用. /** 元素的个数 * ...

  7. 谈谈jQuery中的数据类型检测

    这次是分享jQuery代码中的一些简写技巧,分析jQuery是如何优化代码的,如何用最少的代码来实现jQuery. 在我们工作中也常常会遇到一些数据类型检测,一些方法调用的形式 1 var arr = ...

  8. Ant 与jemter的结合--批量执行jmeter脚本

    一.Ant 介绍&作用: Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发. 作用:打包,部署,运行Java工程 二.下 ...

  9. eclipse中一些常见svn图标的含义

    项目视图   The Package Explorer view - 已忽略版本控制的文件.可以通过Window → Preferences → Team → Ignored Resources.来忽 ...

  10. 目标检测:YOLO(v1 to v3)——学习笔记

    前段时间看了YOLO的论文,打算用YOLO模型做一个迁移学习,看看能不能用于项目中去.但在实践过程中感觉到对于YOLO的一些细节和技巧还是没有很好的理解,现学习其他人的博客总结(所有参考连接都附于最后 ...