說幾個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=2;

main(){
printf("global variable a : %d\n",a);
int a=3;
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=2;
b(){
printf("b : %d\n",a);
}
main(){
int a=4;
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 = 3;
bb();

}

//b.h

void bb(void);

//b.c

#include <stdio.h>
int a = 1;
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 = 3;
bb();

}

//b.h
int a;
void bb(void);

//b.c

#include <stdio.h>
int a = 1;
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 = 3;
bb();

}

//b.h
int a;
void bb(void);

//b.c

#include <stdio.h>
int a = 1;
bb(){
printf ("%d\n",a);
}

上面這個例子中,修改了一下main函數,這時,程序a運行的結果才變為了3,這時因為main函數中的a正是全局變量a,並且把a原來的值改為了3,所以打印3

 

 

//a.c

#include <stdio.h>
#include "b.h"

main(){
a = 3;
printf("%d",a); bb(); }
//b.h int a; void bb(void); //b.c #include <stdio.h> static int a = 1; 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 = 3;
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 = 1;
int b=4;
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的時候編譯器就能幫我們找出錯誤

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM