文章編號(hào):1672-5913(2009)02-0075-05
摘 要:介紹C語(yǔ)言的教科書都會(huì)在某種類型的變量或數(shù)組引出后,緊接著就給出初始化方法。這種分散介紹,既欠完整又拉長(zhǎng)篇幅,還不利于說(shuō)清楚究竟可以用什么,以怎樣的次序做初始化。況且初始化畢竟不是非靜態(tài)局部的必須。本文總體地考察了初始化問題,只要把這些內(nèi)容放在其他知識(shí)之后,就能達(dá)到全面、透徹的目的。
關(guān)鍵詞:C語(yǔ)言;初始化;數(shù)組
中圖分類號(hào):G642
文獻(xiàn)標(biāo)識(shí)碼:B
1 概述
初始化是C系列高級(jí)語(yǔ)言的一種特殊用法。在定義變量或數(shù)組時(shí),在名字后跟隨賦值運(yùn)算符及欲賦的值——稱作初始值,系統(tǒng)就會(huì)在分配內(nèi)存的同時(shí)存入相應(yīng)的初始值。正是這種存儲(chǔ)時(shí)機(jī)的超前性,引出了許多與一般賦值截然不同的語(yǔ)言現(xiàn)象。例如
可以把定義int a, b, c; 改作對(duì)a、c有初始化的定義:
int a = 0, b, c = 100;
此時(shí)系統(tǒng)在給a、c分配內(nèi)存的同時(shí)還會(huì)分別在其中存儲(chǔ)初始值0和100。
由于程序中定義的變量或數(shù)組往往不止一個(gè),它們?cè)陂_始有效的時(shí)間上,一定存在著先后次序,也即起始有效時(shí)刻不盡相同。起始有效時(shí)刻取決于它們出現(xiàn)在定義中的次序。從總體上來(lái)看,全局的起始有效時(shí)刻提前于局部的。也是由于初始化是在定義中給出的,不理解起始有效時(shí)刻的先后,往往會(huì)錯(cuò)誤地把還未有效的名字用在提供初始值的表達(dá)式中。例如
int *p = a, a[10];
是錯(cuò)誤的,問題出在對(duì)p初始化時(shí)a還未有效。
從定義的次序上還能發(fā)現(xiàn),提供初始值的表達(dá)式中錯(cuò)用了一個(gè)未曾初始化的變量的不確定值。例如
int a[10], b = a[1];
也是錯(cuò)誤的,問題出在a[1]未曾初始化,它的值不確定。
2 初始化意義下的常值
有時(shí)提供的初始值必須是常值意義的表達(dá)式,所謂的常值,包括如下兩類:
1) 整型常值
整數(shù)(即整型常量)、字符常量(也是整型常量)或由它們構(gòu)成的表達(dá)式。例如
-3512 + 5 * 6'd''d' + 3
2) 指針型常值
(1) 字面指針常量和字符串常量(代表指針常量)。例如
(int *)1000"I love China"
(2) 具有指針值的表達(dá)式。其中可以出現(xiàn)整型常值,但出現(xiàn)的變量名或數(shù)組名乃至成員名,都必須是全局的或靜態(tài)的,并且還要保證,在計(jì)算該表達(dá)式時(shí),僅僅取用這些名字對(duì)應(yīng)的內(nèi)存地址形成的指針值。例如,假設(shè)有以下的聲明和定義:
struct tag
{
short a;
char b[3];
};
short v, *m, n[7], *p[5], r[5][7];
main()
{
static struct tag vs, ns[4];
/* …… ……*/
}
并且還假設(shè)它們對(duì)應(yīng)內(nèi)存的情況為:
v、m、n、p、r、vs、ns
分別對(duì)應(yīng):5000、5002、5006、5020、5040、10000、10030
那么,從中可以寫出一系列指針型常值,見下表,而且這些常值是什么也體現(xiàn)在表里,其中用陰影淡化的極不常用,列于表中僅為了表格完整,也可以作為指針運(yùn)算的練習(xí)。
3 變量的初始化
3.1 全局和靜態(tài)局部變量的初始化
凡是可以寫出直接由變量名接收常值的賦值語(yǔ)句,都可以寫出相應(yīng)的初始化。例如
int va = 1,
int *m, n[7], *p[5], r[5][7];
main()
{
static int vb = 123;
static int *ma = &v, *mb = n,
*mc = r[3],
*md = (int*)"I love here";
static int **oa = &m, **ob = p;
static int (*qa)[7] = &n,
(*qb)[7] = r, (*qc)[7] = &r[4];
……
}
其中,對(duì)全局變量va和靜態(tài)局部變量vb、ma、mb、mc、md、oa、ob、qa、qb、qc做了初始化。
3.2 非靜態(tài)局部變量的初始化
凡是可以寫出直接由變量名接收賦值的賦值語(yǔ)句,都可以寫出相應(yīng)的初始化。
例如
int v = 1, r[5][7];
main()
{
int n[7];
int va = v + 1, vb = va + 2,
vc = va * vb;
int *ma = n + va,
*mb = &n[vc] - vb;
int (*qa)[7] = r + va,
(*qb)[7] = &r[vc] - vb;
……
}
其中,對(duì)非靜態(tài)局部變量va、vb、vc、ma、mb、qa、qb做了初始化。這方面更多的例子將隨后面的例子一道給出。
結(jié)構(gòu)體變量直接由變量名接收賦值的賦值語(yǔ)句,只有一種形式,即提供值的表達(dá)式得是一個(gè)同類型的結(jié)構(gòu)體變量。然而,結(jié)構(gòu)體變量的初始化還存在另外的形式,也隨后面的例子一道給出。
4 數(shù)組和結(jié)構(gòu)體變量的初始化
這類初始化,是在賦值運(yùn)算符后面跟上由一對(duì)花括號(hào)形成的整體,其中用逗號(hào)間隔的每一項(xiàng)依次是為相應(yīng)元素或相應(yīng)成員提供的值。如果元素或成員仍為數(shù)組或結(jié)構(gòu)體變量,那么為其提供的值還得是由一對(duì)花括號(hào)括起來(lái)的有逗號(hào)間隔的一些項(xiàng),以此類推。最終,從整體外觀看,為初始化提供的可能是有嵌套的花括號(hào)層次結(jié)構(gòu)。
例如,有以下定義:
int r[2][5];
struct tag ns[2];
其中的結(jié)構(gòu)體類型如從前那樣做了聲明。現(xiàn)在來(lái)看怎樣為r和ns提供初始值。
1) 對(duì)r來(lái)說(shuō),它有2個(gè)元素r[0]、r[1],應(yīng)在花括號(hào)內(nèi)準(zhǔn)備2項(xiàng),即 {#, #},而r[0] 又有5個(gè)元素r[0][0]、r[0][1]、r[0][2]、r[0][3]、r[0][4],應(yīng)當(dāng)是包含5項(xiàng)的花括號(hào),即:
{ #, # } => {{#}, #}
=> {{#, #, #, #, #}, # }
關(guān)于r[1] 同理,即有:
{{#, #, #, #, #}, #}
=> {{#, #, #, #, #}, {#, #, #, #, #}}
于是,便得到了最終的花括號(hào)層次結(jié)構(gòu)。
2) 對(duì)ns來(lái)說(shuō),它有2個(gè)元素ns[0]、ns[1],應(yīng)在花括號(hào)內(nèi)準(zhǔn)備2項(xiàng),即{#, #},而ns[0] 又有2個(gè)成員ns[0].u、ns[0].v,應(yīng)當(dāng)是包含2項(xiàng)的花括號(hào),即:
{#, # } => {{#}, # } => {{#, #}, # }
而ns[0].v又有3個(gè)元素ns[0].v[0]、ns[0].v[1]、ns[0].v[2],應(yīng)當(dāng)是包含3項(xiàng)的花括號(hào),即:
{{#, # }, # } => {{#, {#}}, #}
=> {{#, {#, #, #}}, # }
關(guān)于ns[1] 同理,即有:
{{#, {#, #, #}}, # }
=> {{#, {#, #, #}}, {#, #}}
=> {{#, {#, #, #}}, {#, #}}
int r[3][3]={{0, 1, 2},{3, 4, 5},{6, 7}};
此處再一次體會(huì)到,二維數(shù)組的列數(shù)是不可省略的重要信息!
6.2 用字符串常量做初始化
允許使用一個(gè)字符串常量,作為提供初始值所需的諸多字符。
1) 初始化一維字符數(shù)組。例如
char nc[3] = {"123"}; 或
char nc[3] = "123";
都相當(dāng)于
char nc[3] = {'1', '2', '3'};
準(zhǔn)確地說(shuō),此處字符串常量的一個(gè)字符剛好代表一般初始化方法的一項(xiàng)。
2) 初始化二維字符數(shù)組。但一個(gè)字符串常量?jī)H能作為一行的初始值。例如
char rc[2][3] = {{"12"}, {"123"}};
或 char rc[2][3] = {"12", "123"};
都相當(dāng)于
char rc[2][3] = {{'1','2'}, {'1','2', '3'}};
僅能作為一行的初始值意指,盡管以下的初始化方法是允許的,
char rc[2][3] = {'1','2','1','2','3'};
相當(dāng)于
char rc[2][3] = {{'1','2','1'}, {'2','3'}};
但不能寫成:
char rc[2][3] = {"12123"};
或 char rc[2][3] = "12123";
3) 一維字符數(shù)組的方括號(hào)內(nèi)可空。字符串常量結(jié)尾的空字符也算數(shù)。例如
char nc[] = {"123"};
或 char nc[] = "123";
可以決定nc有4個(gè)元素,相當(dāng)于
char nc[] = {'1', '2', '3', ' 本溪| 密云县| 元朗区| 舒城县| 曲麻莱县| 天水市| 崇州市| 汪清县| 临洮县| 庐江县| 云林县| 新巴尔虎左旗| 开平市| 玛多县| 河北省| 丽江市| 壤塘县| 南雄市| 宁都县| 晋江市| 石狮市| 崇义县| 邵阳县| 鄄城县| 井陉县| 长岛县| 兴和县| 昌乐县| 阿瓦提县| 大渡口区| 洛宁县| 故城县| 和平县| 怀柔区| 讷河市| 昌宁县| 芦溪县| 莲花县| 长子县| 吉木乃县| 镇赉县|