c语言交换a b的值里,为什么可以无端出现A和B

c语言的 a=3,b=2,c=1.f=a&b&c,为什么最终f的值为0?_百度知道C习题及答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C习题及答案
上传于||暂无简介
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩18页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢c语言里a+++++b的含义是什么_百度知道C语言中,a++ +b和a+ ++b有什么不同
不同a++ +b是先a+b赋给等式左边的变量,然后a再自加1而a+ ++b是b先自加1,再与a相加后的值赋给等式左边的变量
为您推荐:
其他类似问题
扫描下载二维码C语言全局变量那些事儿 - 推酷
C语言全局变量那些事儿
作为一名程序员,如果说沉迷一门编程语言算作一种乐趣的话,那么与此同时反过来去黑一门编程语言就是这种乐趣的升华。今天我们就来黑一把C语言,好好展示一下这门经典语言令人抓狂的一面。
我们知道,全局变量是C语言语法和语义中一个很重要的知识点,首先它的存在意义需要从三个不同角度去理解:对于程序员来说,它是一个记录内容的变量(variable);对于编译/链接器来说,它是一个需要解析的符号(symbol);对于计算机来说,它可能是具有地址的一块内存(memory)。其次是语法/语义:从作用域上看,带static关键字的全局变量范围只能限定在文件里,否则会外联到整个模块和项目中;从生存期来看,它是静态的,贯穿整个程序或模块运行期间(注意,正是跨单元访问和持续生存周期这两个特点使得全局变量往往成为一段受攻击代码的突破口,了解这一点十分重要);从空间分配上看,定义且初始化的全局变量在编译时在数据段(.data)分配空间,定义但未初始化的全局变量暂存(tentative definition)在.bss段,编译时自动清零,而仅仅是声明的全局变量只能算个符号,寄存在编译器的符号表内,不会分配空间,直到链接或者运行时再重定向到相应的地址上。
我们将向您展现一下,非static限定全局变量在编译/链接以及程序运行时会发生哪些有趣的事情,顺便可以对C编译器/链接器的解析原理管中窥豹。以下示例对ANSI C和GNU C标准都有效,笔者的编译环境是Ubuntu下的GCC-4.4.3。
#ifndef&_H_
#define&_H_
/*&foo.c&*/
#include&&stdio.h&
#include&&t.h&
}&b&=&{&2,&4&};&
&&&&printf(&foo:\t(&a)=0x%08x\n\t(&b)=0x%08x\n&
&&&&&&&&\tsizeof(b)=%d\n\tb.a=%d\n\tb.b=%d\n\tmain:0x%08x\n&,&
&&&&&&&&&a,&&b,&
&b,&b.a,&b.b,&main);&
/*&main.c&*/
#include&&stdio.h&
#include&&t.h&
&&&&foo();&
&&&&printf(&main:\t(&a)=0x%08x\n\t(&b)=0x%08x\n&
&&&&&&&&\t(&c)=0x%08x\n\tsize(b)=%d\n\tb=%d\n\tc=%d\n&,&
&&&&&&&&&a,&&b,&&c,&
&b,&b,&c);&
Makefile如下:
test:&main.o&foo.o&
&&&&gcc&-o&test&main.o&foo.o&
main.o:&main.c&
foo.o:&foo.c&
&&&&rm&*.o&test&
运行情况:
foo:&&&&(&a)=0x&
&&&&(&b)=0x&
&&&&b.a=2&
&&&&b.b=4&
&&&&main:0x&
main:&&&(&a)=0x&
&&&&(&b)=0x&
&&&&(&c)=0x&
&&&&size(b)=4&
这个项目里我们定义了四个全局变量,t.h头文件定义了一个整型a,main.c里定义了两个整型b和c并且未初始化,foo.c里定义了一个初始化了的 结构体,还定义了一个main的函数指针变量。由于C语言每个源文件单独编译,所以t.h分别包含了两次,所以int a就被定义了两次。两个源文件里变量b和函数指针变量main被重复定义了,实际上可以看做代码段的地址。但编译器并未报错,只给出一条警告:
/usr/bin/ld:&Warning:&size&of&symbol&
&changed&from&4&in&main.o&to&8&in&foo.o&
运行程序发现,main.c打印中b大小是4个字节,而foo.c是8个字节,因为sizeof关键字是编译时决议,而源文件中对b类型定义不一 样。但令人惊奇的是无论是在main.c还是foo.c中,a和b都是相同的地址,也就是说,a和b被定义了两次,b还是不同类型,但内存映像中只有一份 拷贝。我们还看到,main.c中b的值居然就是foo.c中结构体第一个成员变量b.a的值,这证实了前面的推断——即便存在多次定义,内存中只有一份初始化的拷贝
另外在这里c是置身事外的一个独立变量。
为何会这样呢?这涉及到C编译器对多重定义的全局符号的解析和链接。在编译阶段,编译器将全局符号信息隐含地编码在可重定位目标文件的符号表里。这里有个“强符号(strong)”和“弱符号(weak)”的概念——前者指的是定义并且初始化了的变量,比如foo.c里的结构体b,后者指的是未定义或者定义但未初始化的变量,比如main.c里的整型b和c,还有两个源文件都包含头文件里的a。当符号被多重定义时,GNU链接器(ld)使用以下规则决议:
不允许出现多个相同强符号。
如果有一个强符号和多个弱符号,则选择强符号。
如果有多个弱符号,那么先决议到size最大的那个,如果同样大小,则按照链接顺序选择第一个。
像上面这个例子中,全局变量a和b存在重复定义。如果我们将main.c中的b初始化赋值,那么就存在两个强符号而违反了规则一,编译器报错。如果 满足规则二,则仅仅提出警告,实际运行时决议的是foo.c中的强符号。而变量a都是弱符号,所以只选择一个(按照目标文件链接时的顺序)。
事实上,这种规则是C语言里的一个大坑,编译器对这种全局变量多重定义的“纵容”很可能会无端修改某个变量,导致程序不确定行为。如果你还没有意识到事态严重性,我再举个例子。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 c语言a b c程序 的文章

 

随机推荐