變數 (程式設計)

在程式設計中，變數是指一個抽象的儲存位址，它含有了被稱為一個值的某種已知或未知的資訊量，並且配對了關聯的符號名稱。通常使用變數名稱參照儲存值；將名稱和內容分開能讓被使用的名稱獨立於所表示的精確訊息之外。電腦原始碼中的識別字能在執行期間綁紮一個值，且該變數的值可能在程式執行期間改變。程式設計中的變數不一定能直接對應到數學中所謂的變數之概念。在程式設計中，變數的值不一定要為方程或數學公式之一部分。程式設計中的變數可使用在一段可重復的程式：在一處賦值，然後使用於另一處，接著在一次賦值，且以相同方式再使用一次。程式設計中的變數通常會給定一個較長的名稱，以描述其用途；數學中的變數通常較為簡潔，只給定一、兩個字母，以方便抄寫及操作。一個變數的儲存位址可以被不同的識別字所參照，這種情況稱之為別名。使用其中一個識別字為變數賦值，將會改變透過另一個識別字存取的值。編譯器必須將代表變數的名稱替代成該資料所在的實際位址。變數的名稱、型別及位址通常會維持固定，但該位址所儲存之資料於程式執行期間則可能會改變。用識別符號引用變數.用識別符號引用變數能對變數進行訪問，從而讀取變數的值，改變變數的值，或者改變變數的屬性。例如，一個變數用識別符號codice_1來引用，設定這個變數的值為1981。如果該變數同時也用識別符號codice_2 來引用，透過codice_2將變數值改變為2010，那麼讀取codice_1的值就是2010而不是1981。如果某種程式語言只允許同一個變數用一個識別符號引用，那麼“該變數的名字”就是有意義的，否則我們稱之為“該變數的名字之一”。例如，在前面的那個例子當中，codice_1是這個變數的名字之一，而codice_2是這個變數的另外一個名字。對變數的操作.在指令式程式語言中，變數的值通常能夠隨時訪問或重新賦值。但在邏輯程式語言中，根據引數透明的需求，變數被繫結到表示式並且在它的整個生命週期中保持同一個值。在指令式程式語言中，同樣的行為用常量來表達，它和通常的變數存在反差。根據程式語言的型別系統的不同，變數可能只儲存一種特定的資料型別。而另外一種情況，變數的資料型別能根據當前賦值而改變，允許單個變數儲存該程式語言支援的任何資料型別。命名規範.與數學當中的量不同，程式設計所用的變數和常量通常都採用多字元的名字，如codice_7或者codice_8。而單個字元的名字一般僅用於輔助性的變數，如codice_9，codice_10，codice_11常作為陣列索引的變數。一些命名規範是作為語法在語言層面強制執行的。在大多數語言當中，變數名不能以數字開頭，不能包含空格符。而標點符號是否允許存在在變數名當中就要視具體語言而定了。很多語言僅僅允許下劃線codice_12存在在變數名當中，而禁止其他所有的標點符號；而有些程式語言，特殊字元作為字首或字尾新增在變數識別符號當中來表明變數的型別。變數名的大小寫敏感性也要視具體語言而定。大多數現代語言是大小寫敏感的，一些較老的語言則不敏感。一些語言保留特定形式的變數名用來內部使用，在很多語言中，以兩根下劃線開頭codice_13的變數名常充當這種角色。在語言語法基本的限制以外，進一步的命名風格規範也很有必要。在機器碼層面，是不會使用變數名的，所以計算機並不關心是否採用了準確的名字。正因為如此，變數名完全是作為程式設計師的工具而存在，藉助這個工具程式設計師能更容易的編寫和理解程式。程式設計師通常建立編碼規範，並且堅持這些規範，幫助對變數命名甚至提供精確的命名規劃。較短的名字便於輸入，但是描述能力較差；較長的名字使程式更容易讀懂，變數的意圖更容易理解。儘管如此，冗長的變數名也可能會導致更難理解的程式碼。在原始碼中.在原始碼中，變數名是將變數和記憶體地址繫結的一種方式。變數值以資料物件的形式儲存在相應的地址內，這樣該資料物件就能透過變數的名字進行訪問和修改了。在電子表格中.在電子試算表中，一個單元格可能包含參考其他單元格的公式。這種被參考的單元格就是一種形式的變數，它的值就是被參考的單元格的值。作用域和生存週期.變數的作用域表示變數在原程式的文字中能被使用的範圍。變數的生存週期表示變數在程式執行過程中具有實際意義的值的時間範圍。更通俗地說，變數的作用域是變數名字的性質，而變數的生存週期是變數本身的性質。變數名字的作用域會影響它的生存週期。作用域是變數語法方面的性質。多數語言對每一個變數定義明確的作用域，這些作用域在同一個程式中可能不同。變數的作用域是指程式中的特定區域，在這些區域中，該變數的名字是有意義的並且變數是“可見的”。在進入作用域時，變數通常開始它的生命週期；而在離開作用域時，變數往往結束了它的生命週期。例如，某個變數的語法作用域僅在特定的語句塊或者子程式中。只有在某個函式中能訪問的變數則被稱為區域性變數，在程式的任何一個地方都能引用的變數被稱為全域性變數。生存週期，則是變數在執行時的性質。在執行時，每次變數與值的繫結都具有自己的生存週期。繫結的生存週期是程式執行過程中的一段時間，在這段時間內，變數始終被關聯到相同的值或者記憶體位置。在閉包的情況中，執行中的程式可能進入和離開某個生存週期很多次。在一些程式碼段中，在一個變數的作用域中可能未被賦值，或者它的值已經被銷燬掉了。這類變數常被稱為“生存週期外”或者“未繫結”。在很多語言中，試圖使用未繫結的變數是一個錯誤。在其他語言中，這種行為會產生不可預期的結果，這樣的變數可能被分配一個新的值。與之對照的是，一個變數繫結到一個超過他作用域的生存週期是被允許的，如Lisp的閉包和C語言的靜態區域性變數。當程式再次執行到變數的作用域時，變數能再次被使用，但還保持上一次的值。為了提高空間效率，變數需要的儲存空間可能要等到變數第一次使用時才申請，不再使用後就刪除。為了避免浪費空間，如果變數聲明瞭但不實際使用，編譯器通常會向程式設計師發出警告。使變數的作用域儘可能的小，被認為是一個好的程式設計方式，這樣程式的不同部分就不會因為意外的改變對方的變數而互相影響了。實現上述目標的通常技術是讓程式的不同部分使用不同名字空間，或者透過動態變數作用使用各自的私有變數。很多程式設計語言使用保留的值表示沒有初始化的變數。型別.在靜態型別語言中，如Java或ML，每個都變數有一個型別，也就是說只有給定種類的值能儲存到該變數中。一個基本型別的變數只能儲存基本型別的值。一個類型別的變數能儲存空值NULL，或者儲存該型別或其子型別的物件。一個介面型別的變數能儲存空值NULL，或者該介面的任何一個實現。一個數組型別能儲存空值NULL或者一個數組。在動態型別語言中，如Python，是值，而不是變數來攜帶型別資訊。在Common Lisp中，這兩種情況同時存在：變數在編譯時具有一個型別；值也有具有一個型別，該型別可以在執行時進行檢查和識別。變數的型別也允許在編譯時多型決定。但是，這和麵向物件的函式呼叫的多型不同。變數常常儲存簡單的資料，如整數和字串。但有些程式設計語言允許變數同時表示多種資料型別。這些語言一般也允許函式引數多型，其函式對變數的操作可同時適用於多種資料型別。例如，函式codice_15可以求一個列表的長度，如果codice_15的型別簽名中包含一個型別變數，就可以實現引數多型。這樣，求列表中的元素個數就與列表元素的型別無關了。引數.函式的形式引數也被稱為變數。例如如下的C++程式碼段：int AddTwo(int x)return x + 2;AddTwo(5); // 結果為7變數codice_2是“形參”，因為當函式被呼叫時會被給定一個值。整數5是“實參”，它給codice_2一個值。在多數語言中，函式引數具有區域性的作用域。這裡的變數codice_2只能在codice_20函式中有效。記憶體分配.變數的記憶體空間分配和它們值的表示方法是多種多樣的，這種區別體現在語言之間，也體現在給定語言的內部使用上。很多語言都實現了局部變數的空間分配方式。區域性變數儲存在呼叫堆疊上，其生存週期維持在單個函式中，函式返回時這些記憶體會自動被回收。對於巨大或者編譯時不知道大小的資料，更常用的方法是使用“引用”。 這時記錄是值的地址而不是值本身，它們是從一種被稱為“棧”的記憶體池中分配的。繫結的變數具有值，一個抽象的值。在程式執行時，變數的值用計算機記憶體中儲存的一些資料物件來表示。程式，或者說執行時環境，必須為每個資料物件設定記憶體。由於記憶體是有限的，為了安置每一個數據物件，當資料物件不再表示某個變數的值時，相應的記憶體會被回收並重新使用。在堆中分配的物件必須被釋放掉，特別是當物件不再被需要時。在具有垃圾回收機制的語言中，當變量出了其作用域再也不能被引用時執行環境會自動地回收物件。在不具有垃圾回收機制的語言當中，如C語言，程式必須顯式地分配記憶體，而且使用結束後還要釋放記憶體，如果不這樣做則會造成記憶體洩漏。在這種情況下，程式執行過程中堆會逐漸消耗，最終因為記憶體耗盡而崩潰。當一個變數指向動態建立的資料結構時，可能其中一些部分只能透過變數間接地訪問。在這種環境下，垃圾回收器必須處理當變量回收時只有一部分記憶體能夠重新回收的情況。