在程序設計中，**指定敘述**（英語：）會將一個特定的值設定到某個特定的儲存位址去，這個位置被標記成一個特定的變數名稱。換句話說，這個敘述會複製一個值到某個特定變數中。在多數的指令式程式語言中，這種敘述是其中最基礎的結構。

指定敘述的通用表示方法通常是 `x = expr`（這種表示法最早源自1949年–1951年时的Superplan（英语：），因為1957年首版的Fortran與C語言而廣為人知），另一種形式則為 `x := expr`（這種形式最早來自ALGOL 58，因為Pascal而盛行）。在這兩種表示法之外，仍然存在許多其他的形式。

對多數的指令式程式語言來說，指定敘述允許某個特定變數，在其生命週期與作用域之中，可以被指定為不同的值，或是重複被值。

语义
--

在指令式編程中，隨著時間改變，不同的值被關聯到某個特定的變數名稱上。變數是數值的容器。可以先指派變數為某個值，在之後再用另一個值來加以取代。在這種模型中，程式的運作，是透過每次成功的指定敘述，來改變其狀態。指令式程式語言，倚靠指定敘述來進行迭代。在最低的層級中，指定敘述是以組合語言指令，如 `MOVE` 或 `STORE`來實作。

以C語言為例，下列的程式碼段落可以作為指定敘述的例子：

```
int x = 10; 
float y;
x = 23;
y = 32.4f;

```

在第一行程式碼中，變數`x`先被宣告為int型別，之後將數值10指定給它。在第二行，變數`y`被宣告為float型別，但沒有值。在第三行，變數`x`被重新指定為數值23。在第四行中，變數`y`被指定為浮點數值32.4f。

单赋值
---

参见：静态单赋值形式
任何改变现存值的赋值（比如`x := x + 1`），在纯函数式语言中都是不允许的。在现今的函数式编程中，赋值是被劝阻的，用以支持也叫做"初始化"的单赋值。单赋值是名字绑定的用例，不同于本文其他部分描述的赋值之处在于，它只能做一次，通常是在变量被创建的时候，不允许后续的重新赋值。

表达式的求值，如果不改变机器的可察见状态，并且对相同的输入产生相同的值，就没有副作用。指令式赋值，在销毁旧值并使之不可获得时，在将旧值替代为新值时，就可能介入了副作用；为此在LISP和函数式编程中，这被称为"破坏性"（destructive）赋值，类似于"破坏性更新"。

在纯函数式语言比如Haskell中，单赋值是赋值的唯一形式，这里没有在指令式语言意义上的变量，而是命名的常量值，并具有可能的合成（compoud）本性，即它们的元素"在需要时"被逐步的定义。纯函数式编程和与之于此共通的数据流程编程，由于值之间相互独立，可以提供在并行计算上的优势，它避免了顺序的一时一步执行的冯·诺伊曼瓶颈。

非纯函数式语言，同时提供了单赋值和真赋值（尽管相比指令式编程语言而言真赋值典型的较少使用）。例如，在Scheme中，单赋值（通过`let`），和真赋值（通过`set!`），二者都可以用于所有变量上，并提供专门的原语（primitive）用于在列表、向量、字符串等之内做破坏性更新。在OCaml中，只有单赋值，通过`let *name* = *value*`语法，被允许用于变量；而破坏性更新，可通过单独的`<-`算符，用于数组的元素和字符串，还可用于已经被编程者显式声明为可变（意味着能够在其初始化声明之后被变更）的记录字段和对象。

使用单赋值的函数式编程语言，包括Clojure（针对数据结构，而非变量）、Erlang（相比Haskell，它接受多次赋值，如果值相等的话）、F#、Haskell、Lava（英语：）、OCaml、Oz（对用数据流变量，而非cell）、Racket（对于一些数据结构如列表，而非符号）、SASL、Scala（对于变量）、SISAL、Standard ML。非回溯的Prolog代码可以被看作"明显的"单赋值，这里明显的含义为，它的（命名）变量可以显式的处在未赋值状态，或只能准确的被设置一次。相反的，在Haskell中，没有未赋值变量，而所有变量可以看作在创建时就被隐式的设定了它的值（更精确的说是设置了计算对象在"在需要时"产生它的值）。

指定語句的回傳值
--------

在一些編程語言中，指定敘述的整個語句可能會傳回某種型別的一個值，而在其它語言中則不會。

在 C 編程語言中指定語句只會單純返回值，而允許這樣子的片語 `x = y = a`，其中指定語句 `y = a` 返回值 `a`，然後將值指定到 `x`。在諸如 `while ((ch = getchar()) != EOF) {*…*}` 的語句中，函數的返回值可用於控制迴圈，同時將相同的值指定給變量 `ch`。

在其它編程語言中例如 Scheme，指定語句的返回值是未定義的，而且這些片語無效。

在 Haskell 中沒有變量指定；但類似於指定的操作（如分配給數組的字段或可變數據結構的字段）通常以 `unit`型別為單位進行求值，`unit` 型別以 `()`表示。這種型別只有一個可能的值，因此不包含任何信息。它通常是純粹為了副作用而評估的表達型別。

赋值的变体形式
-------

特定使用模式也非常常见，因此经常有支持它们的特殊语法。这些主要是减少源代码冗长的语法糖，但也能辅助代码读者理解编程者的意图，并提供给编译器进行可能的优化的线索。

### 增广赋值

条目：增广赋值
所赋予的值依赖于先前的值是很常见的，很多指令式语言，尤其是C及其主要派生者，提供了叫做增广赋值的特殊算符，比如`*=`，则`a = 2*a`可以转而写为`a *= 2`。

### 链式赋值

语句如`w = x = y = z`叫做"链式赋值"，其中`z`的被赋给多个变量`w`、`x`和`y`。链式赋值经常用来初始化多个变量，比如`a = b = c = d = f = 0`。

### 并行赋值

一些编程语言，比如APL、Common Lisp、Go、JavaScript（自从1.7）、Lua、Maple、occam 2、Perl、PHP、Python、REBOL、Ruby、Windows PowerShell，允许多个变量被并行的赋值，语法如下：

```
a, b := 0, 1
```

它同时赋值`0`到`a`和`1`到`b`。这经常叫做**并行**（parallel）赋值；它是CPL语言于1963年介入的，当时名字叫做**同时**（simultaneous）赋值，有时也叫做**多**（multiple）赋值，但这在与**单**（single）赋值一起用时会产生混淆，因为它们不是对比的。如果赋值的右手侧是一个单一变量（比如一个数组或结构），这个特征就叫做**解包**（unpacking）或**解构**（destructuring）赋值：

```
**var** list := {0, 1}
a, b := list
```

这个列表将被解包使得赋值`0`至`a`和`1`至`b`。进一步的：

```
a, b := b, a
```

对换`a`和`b`的值。在没有并行赋值的语言中，这必须通过临时变量来书写：

```
**var** t := a
a := b
b := t
```

因为`a := b; b := a`将把`a`和`b`二者都赋值为`b`最初的值。

一些语言，比如Go和Python，将并行赋值、元组和自动元组解包结合起来，允许从一个单一函数返回多个值，比如如下Python的例子：

```
def f():
    return 1, 2
a, b = f()

```

而其他语言，比如C#，要求使用圆括号的显式元组构造和解构，如下面例子这样：

```
(a, b) = (b, a);

(string, int) f() => ("foo", 1);
var (a, b) = f();

```

这提供了从一个函数返回多个值要使用输出参数的一种替代方式。这最早见于CLU语言（1974年），而CLU推动了一般的并行赋值变得流行。

在C和C++中，逗号运算符，在允许多个赋值出现在一个单一语句上类似于并行赋值，写`a = 1, b = 2`替代`a, b = 1, 2`。这主要用在for循环中，在其他语言比如Go中，被替代为并行赋值。但是上述C++代码不确保完全的同时性，因为代码`a = b, b = a+1`的右侧项是在左侧项之后运算的。在语言如Python中，`a, b = b, a+1`将并发的赋值两个变量，使用最初的`a`的值来计算新`b`的值.

指定與等式符號
-------

参见：關係運算子 § 與賦值運算子的混淆情況

標記法
---

参见：關係運算子 § 標準關係運算符
複製分配的兩個最常見的表示形式是等號（`=`）和冒號等於（`:=`）。這兩種形式都可以在語義上表示賦值語句或賦值運算符（它也具有值），這取決於語言用法。

|  |  |
| --- | --- |
| `*variable* = *expression*` | Fortran, PL/I, C (和派生者比如C++, Java等), Bourne shell, Python, Go (赋值预先声明的变量), R, Windows PowerShell等。 |
| `*variable* := *expression*` | ALGOL (和派生者), Simula, CPL, BCPL, Pascal (和派生者比如Modula), Mary（英语：）, PL/M（英语：）, Ada, Smalltalk, Eiffel, Oberon, Dylan, Seed7（英语：）, Go (声明和定义变量的快捷方式), Io, AMPL, ML, AutoHotkey等。 |
|

其他可能性包括左箭頭或關鍵字，但還有其他更罕見的變體：

|  |  |
| --- | --- |
| `*variable* << *expression*` | Magik（英语：） |
| `*variable* <- *expression*` | F#, OCaml, R, S |
| `*variable* <<- *expression*` | R |
|  `assign("*variable*", *expression*)` | R |
| `*variable* ← *expression*` | APL, Smalltalk |
| `*variable* =: *expression*` | J |
| `LET *variable* = *expression*` | BASIC |
| `let *variable* := *expression*` | XQuery（英语：） |
| `set *variable* to *expression*` | AppleScript |
| `set *variable* = *expression*` | C shell |
| `Set-Variable *variable* *(expression)*` | Windows PowerShell |
| `*variable* : *expression*` | Macsyma（英语：）, Maxima, Rebol |
| `var *variable* *expression*` | mIRC脚本语言（英语：） |
| `*reference-variable* :- *reference-expression*` | Simula |

數學偽代碼分配通常用左箭頭表示。有些平台將表達式放在左側，變量放在右側：

|  |  |
| --- | --- |
| `MOVE *expression* TO *variable*` | COBOL |
| `*expression* → *variable*` | TI-BASIC, Casio BASIC |
| `*expression* -> *variable*` | BETA, R |
| `put *expression* into *variable*` | LiveCode（英语：） |

一些面向運算式的語言比如 Lisp 和 Tcl，對所有語句（包括賦值）統一使用前綴（或後綴）語法。

|  |  |
| --- | --- |
| `(setf *variable* *expression*)` | Common Lisp |
| `(set! *variable* *expression*)` | Scheme |
| `set *variable* *expression*` | Tcl |
| `*expression* *variable* !` | Forth |

另見
--

* 設定運算子
* 算符 (编程)（英语：）
* 名字绑定
* 合一
* 不可变对象
* 常量 (计算机编程)（英语：）

註釋
--

1. 1 2 3  Crossing borders: Explore functional programming with Haskell 的存檔，存档日期November 19, 2010，. by Bruce Tate
2. ↑  Mitchell, John C.. Cambridge University Press. 2003: 23  [3 January 2011]. ISBN 978-0-521-78098-8.
3. ↑   (PDF). gwu.edu.  [20 April 2018]. （原始内容存档 (PDF)于2021-01-18）.
4. ↑  John C. Mitchell.. Cambridge University Press. 2003: 81–82  [3 January 2011]. ISBN 978-0-521-78098-8.
5. ↑  Ruediger-Marcus Flaig.. Wiley-VCH. 2008: 98–99  [25 December 2010]. ISBN 978-3-527-32094-3. （原始内容存档于2017-04-19）.
6. ↑ . Common Lisp Hyperspec. LispWorks.  [23 April 2019]. （原始内容存档于2020-11-30）.
7. ↑  The Go Programming Language Specification: Assignments （页面存档备份，存于）
8. ↑  INMOS Limited (编).. New Jersey: Prentice Hall. 1988. ISBN 0-13-629312-3.
9. ↑  Wall, Larry; Christiansen, Tom; Schwartz, Randal C.  2. Cambridge: O´Reilly. 1996. ISBN 1-56592-149-6.
10. ↑  Lutz, Mark.  2. Sebastopol: O´Reilly. 2001. ISBN 0-596-00085-5.
11. ↑  Thomas, David; Hunt, Andrew.. Upper Saddle River: Addison Wesley. 2001. ISBN 0-201-71089-7.
12. ↑  D.W. Barron *et al.*, "The main features of CPL", *Computer Journal* **6**:2:140 (1963). full text (subscription) Archive.is的存檔，存档日期2012-07-07
13. ↑ . legacy.python.org.  [20 April 2018]. （原始内容存档于2016-05-13）.
14. ↑ . MDN Web Docs.  [20 April 2018]. （原始内容存档于2021-02-10）.
15. ↑  Effective Go （页面存档备份，存于）: for （页面存档备份，存于）,
"Finally, Go has no comma operator and ++ and -- are statements not expressions. Thus if you want to run multiple variables in a for you should use parallel assignment (although that precludes ++ and --)."
16. ↑  Moore, Lawrie.. New York: John Wiley & Sons. 1980. ISBN 0-470-26939-1.
17. ↑  Meyer, Bertrand.. Hemel Hempstead: Prentice Hall International(UK). 1992. ISBN 0-13-247925-7.
18. ↑  Wiener, Richard.. Upper Saddle River, New Jersey: Prentice Hall. 1996. ISBN 0-13-183872-5.
19. ↑  Feinberg, Neal; Keene, Sonya E.; Mathews, Robert O.; Withington, P. Tucker.. Massachusetts: Addison Wesley. 1997. ISBN 0-201-47976-1.
20. ↑ . golang.org.  [20 April 2018]. （原始内容存档于2021-03-18）.
21. ↑  Ullman, Jeffrey D.. Englewood Cliffs, New Jersey: Prentice Hall. 1998. ISBN 0-13-790387-1.
22. ↑  Iverson, Kenneth E.. John Wiley and Sons. 1962. ISBN 0-471-43014-5. （原始内容存档于2009年6月4日）.
23. ↑  Dybvig, R. Kent.. New Jersey: Prentice Hall. 1996. ISBN 0-13-454646-6.
24. ↑  Smith, Jerry D.. New Jersey: Prentice Hall. 1988. ISBN 0-13-496712-7.
25. ↑  Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie.. New Jersey: McGraw-Hill. 1996. ISBN 0-07-000484-6.