非常規(guī)入門C語言:5、標識符、數(shù)據(jù)和作用域
在上一章中,我們了解了地址這個調皮鬼,但是在萬千數(shù)據(jù)中,我們不可能記住所有數(shù)據(jù)的存放的地址,這時,就需要用一個能夠方便記憶的東西來代表數(shù)據(jù)的地址,進而代表數(shù)據(jù)本身。最簡單的方式就是給數(shù)據(jù)起一個名字,而這個名字就對應指定的數(shù)據(jù)。這個“名字”就叫做“標識符”。
既然標識符能夠代表指定的數(shù)據(jù),那么它必然包含一些其他的信息,因為數(shù)據(jù)并不是單純的一個數(shù)值。在前面幾個章節(jié)講解中,無論什么樣的數(shù)據(jù)都至少包含三個重要元素:數(shù)據(jù)的值、數(shù)據(jù)的類型和數(shù)據(jù)的地址,至于數(shù)據(jù)究竟存儲在哪里,并不是最重要的,因為只要知道數(shù)據(jù)的地址,就能夠找到這個數(shù)據(jù)。
而使用標識符表示數(shù)據(jù)本身,那么標識符也應該包含這三個要素:數(shù)據(jù)的值、數(shù)據(jù)的類型和數(shù)據(jù)的地址。
但是我們要考慮到,數(shù)據(jù)是可以重復的,但是標識符是否可以重復呢?
很顯然,不能!為什么呢?
因為引入標識符就是為了方便數(shù)據(jù)的可讀性,我們看到標識符就能夠很快清楚,標識符表達的具體含義。也就是說一旦標識符重復,就違反了我們的初衷。
那什么情況下,標識符能夠“重復”呢?
很明顯,當上一個標識符代表的數(shù)據(jù)被“銷毀”后,同一個標識符就可以表示其他的數(shù)據(jù),那數(shù)據(jù)銷毀的標志是什么呢?這就需要對數(shù)據(jù)進行范圍的限制,因為不論是理論中的數(shù)據(jù)還是自然界中的數(shù)據(jù)也同樣擁有自己的“活動范圍”或“有效范圍”。
針對數(shù)據(jù)的“有效范圍”稱為數(shù)據(jù)的“生命周期”,也可以稱為“作用域”,在作用域內,同樣的標識符不能再次出現(xiàn)。這里存在一個問題:那就是一個班級是可能存在同名的學生,而這些同名的學生都可以在一個教室中“活動”。這是因為這些同名的學生可能屬于不同的家庭,即所屬范圍不一樣。
映射到編程語言中就是,數(shù)據(jù)的標識符在所屬范圍內應當是嚴格唯一的。只要所屬范圍不一樣,那同名數(shù)據(jù)也互不影響。這里的“所屬范圍”也可以視為一種“作用域”,只不過這個“作用域”只存放數(shù)據(jù)。
在眾多數(shù)據(jù)中,有一個特殊的存在,那就是函數(shù)。其實,函數(shù)是一種特殊的數(shù)據(jù),它的內部不僅包含其他的數(shù)據(jù),還有對數(shù)據(jù)的操作指令以及返回值。也就是說,“函數(shù)”本身就是一種數(shù)據(jù)類型,那該怎樣定義出“函數(shù)”呢?
我們先考慮在數(shù)學中函數(shù)是如何表示的,在初等數(shù)學中,函數(shù)的表達式是f(x)=...,同時不同功能的函數(shù)的擁有不同的表達式,不同表達式的內部邏輯也可能是不一樣的。例如直線的表達式:f(x)=ax+b
其中x是自變量,a和b是常數(shù),而f是這個表達式的名字,(x)是名為f的函數(shù)的參數(shù)。而其中的f(x)就是這個表達式的聲明,ax+b是表達式的定義,根據(jù)參數(shù)x求出的結果是函數(shù)f(x)的返回值或結果值。
以此類比,在C語言中,返回值的類型默認為int,即在聲明和定義函數(shù)時,返回值類型一般可以不寫。但參數(shù)的類型必須被指定出來。
大括號以及大括號中的內容就是名為add的函數(shù)的定義,而int add(int num1, int num2)就是函數(shù)的聲明。一般而言,任何數(shù)據(jù)只有聲明后,才能被夠定義,定義又可以稱為“實現(xiàn)”。定義是可以包含聲明的。
這個名為add的函數(shù)的作用域就是雙大括號之間的任何位置。在add函數(shù)中聲明的所有數(shù)據(jù)只能在add函數(shù)內部使用,一旦超出add函數(shù)的范圍,那么超出這個范圍,其內部的數(shù)據(jù)就是無效的、不可訪問的。
既然函數(shù)也是一種數(shù)據(jù),那么就可以將函數(shù)內部的數(shù)據(jù)稱作是函數(shù)的一些較為特殊的屬性,因為這些屬性只能在函數(shù)內部訪問,在函數(shù)外部是不可訪問的。函數(shù)內部的數(shù)據(jù)稱為“局部數(shù)據(jù)”,而數(shù)據(jù)的載體一般又稱為“變量”,于是“局部數(shù)據(jù)”有可以稱為“局部變量”。而一些不能被修改的數(shù)據(jù)被稱為“常量”。
那有沒有辦法能夠讓我們訪問函數(shù)的局部變量呢?當然有!而且還很粗暴:第一種方法就是使用全局變量,全局嘛,不在任何函數(shù)內部,也就意為著誰都可以訪問,沒有任何限制,但會有安全問題。第二種方法就是使用共享區(qū)域的內存。
使用共享內存訪問函數(shù)局部變量
只要是被聲明或這被定義出來的數(shù)據(jù),就必然在會有一個對應的唯一的地址,只要想辦法訪問這個地址,就能夠訪問到函數(shù)的局部變量。那怎樣保存數(shù)據(jù)的地址呢?指針!因為指針就是為了存儲變量的地址而存在的。
指針、標識符、數(shù)據(jù)的地址之間的關系
標識符指的是數(shù)據(jù)本身,指針只存儲數(shù)據(jù)的地址。
而指針本身就是一種數(shù)據(jù),但標識符不是,標識符只是數(shù)據(jù)的助記符。