c语言 函数调用vba 全局变量声明需要声明变量吗

以下试题来自:
单项选择题下列叙述中不正确的是(
)。A.在C语言中调用函数时,只能把实参的值传送给形参,形参的值不能传送给实参B.在C的函数中,最好使用全局变量C.外部变量可以在函数之间传递数据D.自动变量实质上是一个函数内部的局部变量
为您推荐的考试题库
你可能感兴趣的试题
1A.a+=a-=(b=4)*(a=3)B.x%(-3);C.a=a*3=2D.y=float(i)2A.多态性B.继承C.封装性D.模块化3A.&B.-C.||D.~4A.int**q;B.int(*q)();C.int*q;D.int*q();5A.源程序要文档化B.数据说明的次序要规范化C.避免滥用goto语句D.模块设计原则是高耦合、高内聚
热门相关试卷
最新相关试卷更多频道内容在这里查看
爱奇艺用户将能永久保存播放记录
过滤短视频
暂无长视频(电视剧、纪录片、动漫、综艺、电影)播放记录,
使用您的微博帐号登录,即刻尊享微博用户专属服务。
使用您的QQ帐号登录,即刻尊享QQ用户专属服务。
使用您的人人帐号登录,即刻尊享人人用户专属服务。
按住视频可进行拖动
把视频贴到Blog或BBS
当前浏览器仅支持手动复制代码
视频地址:
flash地址:
html代码:
通用代码:
通用代码可同时支持电脑和移动设备的分享播放
收藏成功,可进入查看所有收藏列表
方式1:用手机看
用爱奇艺APP或微信扫一扫,在手机上继续观看:
第2章第8讲 C语言 全局变量声明与定义的差别
方式2:一键下载至手机
限爱奇艺安卓6.0以上版本
使用微信扫一扫,扫描左侧二维码,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:&&
设备搜寻中...
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
连接失败!
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
部安卓(Android)设备,请点击进行选择
请您在手机端下载爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:&&
爱奇艺云推送
请您在手机端登录爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
180秒后更新
打开爱奇艺移动APP,点击“我的-扫一扫”,扫描左侧二维码进行登录
没有安装爱奇艺视频最新客户端?
爸爸去哪儿2游戏 立即参与
第2章第8讲 C语言 全局变量声明与定义的差别
播放量数据:
你可能还想订阅他们:
&正在加载...
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制
安装爱奇艺视频客户端,
马上开始为您下载本片
5秒后自动消失
&li data-elem="tabtitle" data-seq="{{seq}}"& &a href="javascript:void(0);"& &span>{{start}}-{{end}}&/span& &/a& &/li&
&li data-downloadSelect-elem="item" data-downloadSelect-selected="false" data-downloadSelect-tvid="{{tvid}}"& &a href="javascript:void(0);"&{{pd}}&/a&
选择您要下载的《
色情低俗内容
血腥暴力内容
广告或欺诈内容
侵犯了我的权力
还可以输入
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制C语言头文件中定义全局变量的问题_Linux编程_Linux公社-Linux系统门户网站
你好,游客
C语言头文件中定义全局变量的问题
来源:Linux社区&
作者:Sorean
C语言头文件中定义全局变量的问题
问题是这么开始的:
最近在看一个PHP的扩展源码,编译的时候的遇到一个问题:
ld: 1 duplicate symbol for architecture x86_64
仔细看了一下源码,发现在头文件中 出现了全局变量的定义。
简化一下后,可以这么理解:
// t1.h#ifndef T1_H#define T1_H
int a = 0;
#endif//------------------
//t1.c#include "t1.h"#include "t2.h"
int main(){& & return 0;}//-----------------
//t2.h#include "t1.h"//empty//----------------
//t2.c#include "t2.h"//empty//-------
这两个c文件能否通过编译?想必有点经验的必会说 不会,重定义了。
那么是否真的如此?并不这么简单。
&&第一个问题,#ifndef 的这个宏是否防止了重定义(redefinition)?
答案:是。但是是在单个translation unit中(wiki translation unit)。
#ifndef 的头文件宏称为 include guards的(wiki)
我们知道,一个完整的编译的过程是经过
one.c& --&& PREPROCESSOR -&&
tmp.c(temporary)&
-&& COMPILER& -&& one.obj&
-& LINKER -&& one.exe
这三个过程的,而在预编译阶段,便会把include的文件展开,我们使用cc -E 命令来查看t1.c的预编译的结果:
?& t& cc -E t1.c& & & # 1 "t1.c"# 1 "&built-in&" 1# 1 "&built-in&" 3# 321 "&built-in&" 3# 1 "&command line&" 1# 1 "&built-in&" 2# 1 "t1.c" 2
# 1 "./t1.h" 1
int a = 0;# 3 "t1.c" 2# 1 "./t2.h" 1# 4 "t1.c" 2
int main(void){&return 0;}
看到编译器把 t1.h 做了展开,我们看到了 a的定义。
而在t2.c 的预编译结果里,我们同样看到了a的展开定义:
?& t& cc -E t2.c& # 1 "t2.c"# 1 "&built-in&" 1# 1 "&built-in&" 3# 321 "&built-in&" 3# 1 "&command line&" 1# 1 "&built-in&" 2# 1 "t2.c" 2# 1 "./t2.h" 1# 1 "./t1.h" 1
int a = 0;# 2 "./t2.h" 2# 2 "t2.c" 2
所以到了Link阶段,编译器会看见两个a的定义。原因在于 include guards 只在同一个translation unit(一个c文件和include的文件的编译过程)内起作用,两个编译单元是编译过程是分开的,所以无法察觉到另外一个里面的#ifdefine内容,可以这么理解:
t1.c -& t1.s -& t2.o& & & & & & & & & & & & &
\& & & & & & & & & & & & & & *-& - t.otu& & & & & & & & & & & & &
/t2.c -& t2.s -& t2.o
所以,在头文件中是不应该define 变量,只应该declare。
include guards 是为了防止两个文件相互引用而造成的循环引用问题。读者可以试试去除include guards,看看效果。
以上的解答也同时解释了 为什么 include guards 没有在这个例子下起到防止重定义的作用。
那么,如何强制在头文件中定义全局变量呢?
正确的做法是头文件declare,c文件define,老生常谈的问题,不再赘述。这里提供两个技巧:对于函数,有人给出这么个办法,添加inline或者static 关键字。
或者有人直接这么搞:
#ifdef DEFINE_GLOBALS#define EXTERN#else#define EXTERN extern#endifEXTERN int global1;EXTERN int global2;
那么在头文件中定义全局变量真的一定是错误的吗?
答案是不一定。
如果我们写这样一个c文件:
int main(void){& & return 0;}
你肯定认为是重定义了,不过你可以试试 cc ,并不会报错,甚至没有warning。
原因其实在于 tentative defination,C99里的相关定义是
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition.If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
意义是,如果declare了一个变量,但是没有初始化,在同一个translation unit结束后,还没有发现初始化,那么应该把这个变量赋值为0。所以,如果依据C99的规则,你在头文件中写入
仍然会被编译为int a = 0。所以多次包含,仍然会重定义报错。
而gcc vc并没有完全遵循这个标准,C99中最后面还有一段:
Multiple external definitions
There may be more than one external definition for the identifier of an object, with or without the explicit use o if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
多么尴尬的一段话,我们可以理解为gcc 和 vc允许在整个程序编译过程中的&tentative definition&,而非单一个"translation unit"内。
那么我们便可以理解之前两个int a的不会报错的场景了。gcc vc 视这样的没有初始化的变量为extern而非define。
同样可以理解的是,如果我们添加了初始化值:
int a = 0;int a = 0;int main(void){& & return 0;}
则会报错了:
?& t& cc t1.cppt1.cpp:5:5: error: redefinition of 'a'& & ^./t1.h:4:5: note: previous definition is here& & ^t1.cpp:6:5: error: redefinition of 'a'& & ^./t1.h:4:5: note: previous definition is here& & ^2 errors generated.
结合tentative definition的定义,便不难理解了。
到这里,细心的读者可能发现,我们这里的tentative definition只局限于C语言,是的。C++并不认可这一概念,把所有的 视为变量定义。所以,如果使用c++,这些又会全部变成 redefinition 或者 duplicate symbol了。
吐槽:一个看似简单的问题,查阅了一天的资料,引申出这么多概念,才彻底弄明白,我真的学过C嘛( ⊙ o ⊙ )?
本文永久更新链接地址:
相关资讯 & & &
& (10/23/:52)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款随笔 - 337&
文章 - 0&评论 - 14&trackbacks - 0
&&& C语言中全局变量的定义与声明困扰着许多C语言初学者。本文讲述了全局变量定义与声明的用法,而且本为也将阐述这种用法的内在原理。我们先从两个错误例子引入,以下两个例程都在vc6.0平台上测试。
两种错误例程
1.unresolved external symbol
例子包含两个C文件(test.c)和(first.c)和一个头文件(test.h)。下边具体展示下它们的代码。
test.h内容
#ifndef _TEST_H#define _TEST_H&&&&
test.c内容
#include &stdio.h&#include "test.h"extern void Fis_Cal(void);void main(void){&Fis_Cal();&&printf("the present value of count is %d\n",count);}
first.c内容
#include &stdio.h&#include "test.h"void Fis_Cal(void){&printf("the last value of count is %d\n",count);&count = 1;}
错误分析:test.h头文件中声明了全局变量count,但是在两个C文件中都没有对count进行定义,所以才会出现unresolved external symbol。
一种解决方法:随便在两个C文件中加入一句&&就OK了。例如我们加到test.c中,代码如下。&
#include &stdio.h&#include "test.h"extern void Fis_Cal(void); void main(void){&Fis_Cal();&printf("the present value of count is %d\n",count);}
说明:加入的&&就是对count的定义,默认的将其初始化为0。
结论:这种错误原因是&只声明未定义&。
2.multiply defined symbols found
还是如此,三个文件。但是,两个C文件与例程一中的文件一样,改动的只是头文件。
test.h内容
#ifndef _TEST_H#define _TEST_H&&
可以看到,与例程一仅仅差了一个&extern&关键词。
错误分析:test.h头文件中定义了全局变量count,但是在两个C文件都通过&#include "test.h"&这句话对&&进行了引用,所以造成了重复定义的错误。
一种解决方法:添加一个&first.h&的头文件,并且更改first.c的内容,具体更改如下。
first.h内容
#ifndef _FIRST_H#define _FIRST_H
first.c内容
#include &stdio.h&#include "first.h"void Fis_Cal(void){&printf("the last value of count is %d\n",count);&count = 1;}
说明:经过这样的修改,原来的test.c中就包含了count的定义,而first.c中就包含了对count的声明,重复定义错误就得到解决。
结论:这种错误原因是&多个C程序都包含了定义全局变量的头文件&。&
&&& 我认为&&是对全局变量的定义,而&extern int count&是对全局变量的声明,目的是让其他文件也使用这个全局变量。下边我们来挖掘全局变量的定义与声明的内涵。
&&& 全局变量要么初始化(非零),要么没有初始化(为零)。非零时存储在程序中的data段,零时存储在程序的bss段。这谈了程序(.bin或者.hex)的结构。我再讲一下程序的启动,程序在启动(boot)过程中,通常都会运行一个叫bootloader的引导程序,这个引导程序干了很多事情,其中有一最重要的任务就是把程序(test段和rodata段)拷贝到内存,还包括data段的拷贝和bss段初始化。我们着重讲一下data段的拷贝和bss段初始化。
&&& 我们的编译器会为我们定义的全局变量分配内存(地址),而且给我们的全局变量赋初值(写内存或清零),以后我们的程序就会根据需要来读这个全局变量(地址)或者修改这个全局变量(写内存)。初值为零时就在bss段,这个段初始化代码会将这部分清零。初值非零时,初始化代码会将全局变量的初值拷贝到data段。
&&& 那么,显然全局变量的初值只有一个。我们程序中的全局变量的定义就是对全局变量分配内存并赋初值。而全局变量的声明是为了跨文件使用全局变量的需要,通过"extern"关键词来将全局变量引出。&
顺便说一下C语言的存储类说明符,这能帮助我们加深理解。
C语言的存储类说明符
&&& &Auto 只在块内变量声明中被允许, 表示变量具有本地生存期。
&&& &Extern 出现在顶层或块的外部变量函数与变量声明中,表示声明的对象具有静态生存期, 连接程序知道其名字。
&&& Static 可以放在函数与变量声明中,在函数定义时,只用于指定函数名,而不将函数导出到链接程序,在函数声明中,表示其后边会有定义声明的函数,存储类型static.在数据声明中,总是表示定义的声明不导出到连接程序关键字。
一种更好的声明与定义方式
test.h内容&
#ifndef _TEST_H#define _TEST_H&#ifdef GLOBALS#else #endif&
test.c内容
#define GLOBALS#include &stdio.h&#include "test.h"extern void Fis_Cal(void);void main(void){&Fis_Cal();&printf("the present value of count is %d\n",count);}
first.c内容
#include &stdio.h&#include "test.h"void Fis_Cal(void){&printf("the last value of count is %d\n",count);&count = 1;}
说明:这种方法可以只定义一个头文件实现在不同C文件中分别实现定义与声明。&#define GLOBALS&只在当前定义的test.c文件中有效,所以在test.c中#include "test.h"预处理后,加入的是int count,而first.c中加入的""。其实还有一种书写方法,也能实现这个效果。
test.h内容&
#ifndef _TEST_H#define _TEST_H&#ifdef GLOBALS#define EXT#else#define EXT extern#endif
阅读(...) 评论()二次元同好交流新大陆
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
爱生活,爱户外,爱技术
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
工程包含a.c
在a.c文件里有一个全局变量
b.c里有一个全局变量
问:1、若b.c里的函数要改变a.c 里全局变量的值,可否直接在b.c
里extern list 然后直接调函数修改?
2、a.c 调用b.c里的函数test_change(test)修改test的值
然后a.c再调用b.c里的函数test_show(test)显示test的值,这里的test值是前面test_change修改的值吗?我的意思是,b.c里的全局变量保存在哪里?不需要return给a.c也能保存值吗?1. 可以。全局变量本身具有外部链接特性。extern list可以让编译器在编译时暂时用一个临时的标识符表示list,等到链接时去其他链接文件里找到正确的list的定义,并替换掉b.c中使用到的地方,最终相当于b.c中直接使用了a.c中的list。
2. 如果你的test_change里面确实有修改到的全局的test,那这里的test值就是test_change修改的值。
全局变量的作用域是整个源程序,它和静态变量一样都统一保存在全局静态存储区。因此对于整个源程序来说(包括a.c和b.c),只有一个test和list,在哪里对它进行修改,效果都是一样的
阅读(1184)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'C语言中跨文件的全局变量',
blogAbstract:'首先看一段代码',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:5,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'爱生活,爱户外,爱技术',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 全局变量声明 的文章

 

随机推荐