一:

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区别的地方以及静态变量,全局变量的区别的更多相关文章

  1. python中非关键字可变长参数和关键字变量参数的区别

    #非关键字可变长参数 def add(*arg):    return type(arg) print add() #打印结果 <type 'tuple'> #关键字变量参数 def ab ...

  2. Python的学习(二十一)----Python的静态变量

    前段时间在论坛里面有人提问说, class foo(): member1 member2 ... self.member1 foo.member2 其中的两个成员member1, member2有什么 ...

  3. Java笔记_静态变量和实例变量的区别

    这里简单做一下笔记,区分Java全局变量里的静态变量与实例变量. 1.Java里的全局变量 首先了解Java里的全局变量,也叫成员变量. 特点: (1).一个类中既不在方法体内,也不在程序块内定义的变 ...

  4. python 里面的单下划线与双下划线的区别

    python 里面的单下划线与双下划线的区别 Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __ ...

  5. python中,花括号,中括号,小括号的区别

    python中,花括号,中括号,小括号的区别 Python主要有三种数据类型:字典.列表.元组.其分别由花括号,中括号,小括号表示. 如: 字典:dic={'a':12,'b':34} 列表:list ...

  6. python 里面的单下划线与双下划线的区别(私有和保护)

    Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下划 ...

  7. ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数

    一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...

  8. 我的Python学习笔记(三):私有变量

    一.私有变量的定义 在Python中,有以下几种方式来定义变量: xx:公有变量 _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入 ...

  9. php--纯静态和伪静态的区别与关系

    先前说了什么是纯静态和伪静态,现在介绍一下他们的区别? 首先肯定的是纯静态和伪静态都是SEO的产物,但纯静态和伪静态还是有很大区别的.纯静态是生成真实的HTML页面保存到服务器端,用户访问时直接访问这 ...

随机推荐

  1. Django-website 程序案例系列-2 字典操作

    设置一个全局字段: USER_DICT = { 'k1': 'root1', 'k2': 'root2', 'k3': 'root3', } def index(request): return re ...

  2. BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  3. startSSL 申请免费的SSL证书

    打开网址https://www.startssl.com/?app=12,选择Sign-up注册. 输入个人注册信息 需注意以下几点:(1)地址必须详细,否则你会收到这样的邮件: Please pro ...

  4. [并查集+LCA USACO18OPEN ] Disruption

    https://www.luogu.org/problemnew/show/P4374 一看这道题就是一个妙题,然后题解什么树链剖分...珂朵莉树... 还不如并查集来的实在!我们知道并查集本来就是路 ...

  5. [luogu1373]小a和uim之大逃离【动态规划】

    传送门:https://www.luogu.org/problemnew/show/P1373 定义状态是:\(f[i][j][h][0..1]\)表示在\([i,j]\)两个人相差为h,让某一个人走 ...

  6. 【数学】NOIP数论内容整理

    NOIP数论内容整理 注:特别感谢sdsy的zxy神仙以及lcez的tsr筮安帮助审稿 一.整除: 对于\(a,b~\in~Z\),若\(\exists~k~\in~Z\),\(s.t.~b~=~k~ ...

  7. javascript面向对象精要第一章原始类型和引用类型整理精要

  8. 盘点 php 里面那些冷门又实用的小技巧

    1.实用某个字段索引二维数组 取出一个数组的一个字段的值的数组,我们可以使用 array_column, 这个方法还有另外一个用法,如 array_column($array, null, 'key' ...

  9. MUI 当input聚焦之后,弹出自带的键盘之后,内容往上移动

    1)有时候为了用户更好的体验,当input聚焦之后,手机自带的键盘弹出的时候,页面的内容也要跟着滚动,好让键盘不遮住input 只要把input标签放到mui-content这个类里面就可以了 < ...

  10. POJ1185 状压dp(二进制//三进制)解法

    很显然这是一道状压dp的题目 由于每个最优子结构和前两行有关,一个显而易见的想法是用三维dp[i][j][k]用来记录在第i行下为j状态,i - 1行为k状态时的最大值,然而dp[100][1 < ...