说几个python与c区别的地方以及静态变量,全局变量的区别
一:
python代码:
a = 2
def b():
print a
a = 4
print a
b()
在b函数中,有a=4这样的代码,说明a是函数b内部的局部变量,而不是外部的那个值为2的全局变量a,那么第一行代码就报错了,原因是local variable 'a' referenced before assignment
而在c中就不会报错:
#include <stdio.h>
int a=; main(){
printf("global variable a : %d\n",a);
int a=;
printf("local variable a : %d\n",a);
}
/*结果:
global variable a : 2
local variable a : 3
*/
在main函数中,变量a开始为全局变量,后来为本地变量,这在Python中是不允许的
二:
在python中是正确的:
def b():
print x
x=3
b()
但是在c中在编译阶段就会报错:
#include <stdio.h>
b(){
printf("b : %d\n",a);
}
int a =3;
main(){
b();
}
错误在第三行,错误原因是变量a未声明,如果将上述代码改一下,改成:
#include <stdio.h>
extern int a;
b(){
printf("b : %d\n",a);
} main(){
b();
}
则虽然编译通过了,但是链接的时候却报错了,extern int a;的意思是,变量a在别处有定义,暂时先让我编译通过。于是虽然编译阶段是通过了,但等到链接的时候,由于本源文件没有include其他源文件,导致连接器最终还是没能找到变量a的定义,于是就报错了
以上是python和c语言不同之处,下面再说一个相同的地方,大家都知道python是有闭包存在的:
a=2
def aa():
print a
def bb():
a=4
aa() bb()#打印2
在c语言中同样存在:
#include <stdio.h> int a=;
b(){
printf("b : %d\n",a);
}
main(){
int a=;
b();//打印2
}
/*但是如果把main函数改为:
main(){
a=4;
b();//将不在打印4,而是2.
}*/
明白了上述问题,我们来看几个例子:
现在同一文件夹下有如下文件:

编译a.c: cc -c a.c; 生成a.o
编译b.c: cc -c b.c; 生成b.o
链接a.o,b.o生成最终可执行文件a: cc -o a a.o b.o

//a.c #include <stdio.h>
#include "b.h"
main(){
int a = ;
bb(); } //b.h void bb(void); //b.c #include <stdio.h>
int a = ;
bb(){
printf ("%d\n",a);
}
执行./a,执行结果:打印的是1,而不是3
在本例中,b.c中的a属于公共的通用的变量,b函数里的a也正是这个公共变量a。任何源文件的代码在引用这个变量之前,只要有这个变量的声明,或者该源文件include的文件有这个变量的声明,那么这个源文件就可以访问这个变量或者修改这个变量的值。本例中,a.c文件就没有声明该变量。
//a.c #include <stdio.h>
#include "b.h"
main(){
int a = ;
bb(); } //b.h
int a;
void bb(void); //b.c #include <stdio.h>
int a = ;
bb(){
printf ("%d\n",a);
}
上面这个是在b的头文件中加入了变量a的声明。a程序运行的结果还是打印1,而不是3.因为虽然全局公共变量a虽然被带到了源文件a.c中了,但是在mian函数中的a是局部变量a,而不是全局公共变量a,而bb函数中的a是全局公共变量a,所以打印1.
//a.c #include <stdio.h>
#include "b.h"
main(){
a = ;
bb(); } //b.h
int a;
void bb(void); //b.c #include <stdio.h>
int a = ;
bb(){
printf ("%d\n",a);
}
上面这个例子中,修改了一下main函数,这时,程序a运行的结果才变为了3,这时因为main函数中的a正是全局变量a,并且把a原来的值改为了3,所以打印3
//a.c #include <stdio.h>
#include "b.h" main(){
a = ;
printf("%d",a);
bb(); } //b.h
int a;
void bb(void); //b.c #include <stdio.h>
static int a = ;
bb(){
printf ("%d\n",a);
}
上面这个例子中,修改了一下b.c,将变量a由原来的全局公共变量变成了本地静态变量,那么这个变量的作用域仅仅是b.c,我们知道include只是将文件加载进来,
所以,a.c源文件完全等价于:
//a.c
#include <stdio.h>
int a;
void bb(void);
main(){
a = ;
printf("%d",a);
bb(); }
所以a.c中的变量a是全局公共变量a,而main函数中的a也正是这个,而bb中的a是b.c文件中的本地静态变量a,所以才会先打印3,后打印1
但是上面这个例子虽然语法上是没有任何错误的,但是却失去了头文件库文件的意义。
正确的写法是:
//a.c #include <stdio.h>
#include "b.h"
main(){
printf("%d",b);
bb(); } //b.h
int b;
void bb(void); //b.c #include <stdio.h>
#include "b.h" static int a = ;
int b=;
bb(){
printf ("%d\n",a);
}
其中a.c可以说成主程序文件,而b.h是这个主程序文件正常运行所依赖的头文件,而b.c是这个主程序文件正常运行所依赖的库文件。
我们把b.c这个库文件中,所有的需要被其他程序引用的变量或函数或者其他什么的,都列出来,做成一个文件,这个文件就是b.c的头文件,特别要注意到,由于
b.c中的变量a是本地私有的变量,其他程序文件用不到这个变量,所以就没有出现在头文件b.h中
还有就是,b.c是要包含他自己的头文件b.h的,虽然不包含也不会报错,但这是一个很好的习惯,这样我们在编译b.c的时候,编译器就能帮我们检测头文件中的声明与库文件是否保持一致,试想一下,如果b.h中,我们写的是float int b;那么有了include这句话,在编译b.c的时候编译器就能帮我们找出错误
说几个python与c区别的地方以及静态变量,全局变量的区别的更多相关文章
- python中非关键字可变长参数和关键字变量参数的区别
#非关键字可变长参数 def add(*arg): return type(arg) print add() #打印结果 <type 'tuple'> #关键字变量参数 def ab ...
- Python的学习(二十一)----Python的静态变量
前段时间在论坛里面有人提问说, class foo(): member1 member2 ... self.member1 foo.member2 其中的两个成员member1, member2有什么 ...
- Java笔记_静态变量和实例变量的区别
这里简单做一下笔记,区分Java全局变量里的静态变量与实例变量. 1.Java里的全局变量 首先了解Java里的全局变量,也叫成员变量. 特点: (1).一个类中既不在方法体内,也不在程序块内定义的变 ...
- python 里面的单下划线与双下划线的区别
python 里面的单下划线与双下划线的区别 Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __ ...
- python中,花括号,中括号,小括号的区别
python中,花括号,中括号,小括号的区别 Python主要有三种数据类型:字典.列表.元组.其分别由花括号,中括号,小括号表示. 如: 字典:dic={'a':12,'b':34} 列表:list ...
- python 里面的单下划线与双下划线的区别(私有和保护)
Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下划 ...
- ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数
一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...
- 我的Python学习笔记(三):私有变量
一.私有变量的定义 在Python中,有以下几种方式来定义变量: xx:公有变量 _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入 ...
- php--纯静态和伪静态的区别与关系
先前说了什么是纯静态和伪静态,现在介绍一下他们的区别? 首先肯定的是纯静态和伪静态都是SEO的产物,但纯静态和伪静态还是有很大区别的.纯静态是生成真实的HTML页面保存到服务器端,用户访问时直接访问这 ...
随机推荐
- 在property里面设置版本号可灵活引用
- 洛谷P2698 [USACO12MAR]花盆Flowerpot
P2698 [USACO12MAR]花盆Flowerpot 题目描述 Farmer John has been having trouble making his plants grow, and n ...
- ZJOI2019 Day1 题解
想要继续向前,就从克服内心的恐惧开始. 麻将 题意 在麻将中,我们称点数连续的三张牌或三张点数一样的成为面子,称两张点数一样的牌为对子.一副十四张麻将牌的胡牌条件是可以分成四个面子和一个对子或者分成七 ...
- Django-website 程序案例系列-7 创建多对多关系表
创建多对多关系表: 方式一:一共三张表其中有一张中间表需要手工建立(建议使用第一种方式自定制程度高) class Host(models.Model): hostname = models.CharF ...
- BZOJ4445 SCOI2015小凸想跑步(半平面交)
考虑怎样的点满足条件.设其为(xp,yp),则要满足(x0-xp,y0-yp)×(x1-xp,y1-yp)<=(xi-xp,yi-yp)×(xi+1-xp,yi+1-yp)对任意i成立.拆开式子 ...
- Luogu3676 小清新数据结构题(树链剖分+线段树)
先不考虑换根.考虑修改某个点权值对答案的影响.显然这只会改变其祖先的子树权值和,设某祖先原子树权值和为s,修改后权值增加了x,则对答案的影响为(s+x)2-s2=2sx+x2.可以发现只要维护每个点到 ...
- 【题解】 bzoj3450 JoyOI1952 Easy (期望dp)
题面戳我 Solution 期望的题目真心不太会 定义状态\(f[i]\)表示到第\(i\)期望长度,\(dp[i]\)表示期望分数 如果上一步的持续\(o\)长度为\(L\),那么贡献是\(L^2\ ...
- [luogu4568][bzoj2763][JLOI2011]飞行路线
题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为00到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定 ...
- pandas merge
merge pandas的merge方法提供了一种类似于SQL的内存链接操作,官网文档提到它的性能会比其他开源语言的数据操作(例如R)要高效. merge的参数 on:列名,join用来对齐的那一列的 ...
- LOJ#2320 生成树计数
解:讲一个别的题解里我比较难以理解的地方,就是为什么可以把这两个东西合起来看成某一个连通块指数是2m而别的指数都是m. 其实很好理解,但是别人都略过了......把后面的∑提到∏的前面,然后展开,也可 ...