中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

qq郵箱登錄入口網(wǎng)頁版廣州seo網(wǎng)站推廣公司

qq郵箱登錄入口網(wǎng)頁版,廣州seo網(wǎng)站推廣公司,網(wǎng)站建站是 什么,上海做小程序歡迎關(guān)注博主 Mindtechnist 或加入【智能科技社區(qū)】一起學習和分享Linux、C、C、Python、Matlab,機器人運動控制、多機器人協(xié)作,智能優(yōu)化算法,濾波估計、多傳感器信息融合,機器學習,人工智能等相關(guān)領(lǐng)域的知識和技術(shù)。 …

在這里插入圖片描述

歡迎關(guān)注博主 Mindtechnist 或加入【智能科技社區(qū)】一起學習和分享Linux、C、C++、Python、Matlab,機器人運動控制、多機器人協(xié)作,智能優(yōu)化算法,濾波估計、多傳感器信息融合,機器學習,人工智能等相關(guān)領(lǐng)域的知識和技術(shù)。


C語言標準定義的32個關(guān)鍵字

    • 1. 數(shù)據(jù)類型關(guān)鍵字(12個)
      • (1) 聲明和定義的區(qū)別
      • (2) 數(shù)據(jù)類型關(guān)鍵字
    • 2. 控制語句關(guān)鍵字(12個)
    • 3. 存儲類關(guān)鍵字(5個)
    • 4. 其他關(guān)鍵字(3個)


專欄:《精通C語言》


1. 數(shù)據(jù)類型關(guān)鍵字(12個)

C語言中的數(shù)據(jù)類型主要有下面幾種。實際上,數(shù)據(jù)類型可以理解為固定大小內(nèi)存塊的別名,給變量指定類型就是告訴編譯器給該變量分配多大的內(nèi)存空間,而變量相當于是內(nèi)存塊的門牌號。

在這里插入圖片描述

(1) 聲明和定義的區(qū)別

定義可以看作是聲明的一個特例,并非所有的聲明都是定義??梢酝ㄟ^是否分配內(nèi)存來區(qū)分定義和聲明,定義會建立存儲空間,而聲名不會建立存儲空間。

int function()
{//定義int val; //定義一個變量val,此時會給val分配內(nèi)存,由數(shù)據(jù)類型int決定分配多大內(nèi)存,int為4字節(jié)。val = 10; //可以為val賦值。//聲明extern int val_2; //聲明變量val_2,不會建立內(nèi)存。//val_2 = 10; //error: 聲明不會建立內(nèi)存,沒有內(nèi)存空間所以無法賦值。return 0;
}
  • 定義:定義是指創(chuàng)建一個對象并為這個對象分配一塊內(nèi)存,同時將變量名和這個內(nèi)存塊進行綁定。但是,同一個變量在同一作用域只能定義一次,如果多次定義的話,編譯器會提示重定義錯誤。
  • 聲明:
    • 告訴編譯器,某個名稱已經(jīng)被預定了,其他對象/內(nèi)存塊不能再使用這個名稱。
    • 告訴編譯器,某個名稱已經(jīng)綁定好內(nèi)存塊了,該對象是在其他位置定義的,這里用到本名稱時不要報錯。

(2) 數(shù)據(jù)類型關(guān)鍵字

char:聲明字符型變量。

char類型用于存儲一個單一字符,即1字節(jié)存儲單元。在給char類型變量賦值時需要把值用英文半角單引號’'引起來,存儲時并非真正把該字符放到存儲空間,而是把該字符對應的ASCII碼存放到存儲單元中。(也可以把char類型看作是1字節(jié)整形)。

ASCII對照表如下

ASCII值控制字符ASCII值字符ASCII值字符ASCII值字符
0NUT32(space)64@96、
1SOH33!65A97a
2STX34"66B98b
3ETX35#67C99c
4EOT36$68D100d
5ENQ37%69E101e
6ACK38&70F102f
7BEL39,71G103g
8BS40(72H104h
9HT41)73I105i
10LF42*74J106j
11VT43+75K107k
12FF44,76L108l
13CR45-77M109m
14SO46.78N110n
15SI47/79O111o
16DLE48080P112p
17DCI49181Q113q
18DC250282R114r
19DC351383S115s
20DC452484T116t
21NAK53585U117u
22SYN54686V118v
23TB55787W119w
24CAN56888X120x
25EM57989Y121y
26SUB58:90Z122z
27ESC59;91[123{
28FS60<92/124|
29GS61=93]125}
30RS62>94^126`
31US63?95_127DEL

在上面的ASCII碼表中,ASCII值0-31表示非打印控制字符,用于控制打印機等外圍設(shè)備;32-126為打印字符,這些字符在鍵盤上都可以找到;127表示del命令。

轉(zhuǎn)義字符

轉(zhuǎn)義字符含義ASCII碼值(十進制)
\a警報007
\b退格(BS) ,將當前位置移到前一列008
\f換頁(FF),將當前位置移到下頁開頭012
\n換行(LF) ,將當前位置移到下一行開頭010
\r回車(CR) ,將當前位置移到本行開頭013
\t水平制表(HT) (跳到下一個TAB位置)009
\v垂直制表(VT)011
\代表一個反斜線字符""092
代表一個單引號(撇號)字符039
"代表一個雙引號字符034
?代表一個問號063
\0數(shù)字0000
\ddd8進制轉(zhuǎn)義字符,d范圍0~73位8進制
\xhh16進制轉(zhuǎn)義字符,h范圍09,af,A~F3位16進制

int:聲明整型變量。

在C語言標準中并沒有明確規(guī)定整型數(shù)據(jù)的長度,整型數(shù)據(jù)在內(nèi)存中所占的字節(jié)數(shù)與操作系統(tǒng)有關(guān)系。(一般為4字節(jié))

打印格式含義
%d輸出一個有符號的10進制int類型
%o輸出8進制的int類型
%x輸出16進制的int類型,字母以小寫輸出
%X輸出16進制的int類型,字母以大寫寫輸出
%u輸出一個10進制的無符號數(shù)

short:聲明短整型變量。

長度一般不長于int型數(shù)據(jù)。(一般為2字節(jié))

long:聲明長整型變量。

長度一般不短于int型數(shù)據(jù)。(Windows為4字節(jié);Linux為4字節(jié)(32位),8字節(jié)(64位)。)

打印格式含義
%hd輸出short類型
%d輸出int類型
%l輸出long類型
%ll輸出long long類型
%hu輸出unsigned short類型
%u輸出unsigned int類型
%lu輸出unsigned long類型
%llu輸出unsigned long long類型

float:聲明單精度浮點型變量。

浮點型變量也叫做實型變量,用于存儲小數(shù)數(shù)值。float單精度浮點型一般占用4字節(jié)存儲空間,7位有效數(shù)字。

double:聲明雙精度浮點型變量。

double雙精度浮點型精度高于float單精度浮點型,占用8字節(jié)存儲空間,15-16位有效數(shù)字。

浮點型變量存儲的是小數(shù),并且浮點型變量的存儲單元是有限的,這就導致一個小數(shù)有效位以外的數(shù)字將被舍去,這樣便會出現(xiàn)一些誤差。尤其是float單精度浮點型,有時候?qū)⒁粋€小數(shù)賦值給一個float型變量,然后打印該浮點型變量都會出現(xiàn)和原小數(shù)不一致這樣的情況。一般使用double雙精度可以提升精度,并且在C語言中,一個小數(shù)后面不加f則被認為是雙精度double類型,只有小數(shù)后面加f才表示float類型,比如3.14f。

signed:聲明有符號類型變量。

缺省時,編譯器默認為signed有符號類型。在計算機中,所有的數(shù)據(jù)都是以01的二進制形式來存儲的,對于有符號數(shù)來說如何表示一個數(shù)值的正負是一個問題,因此便有了原碼、反碼和補碼。

  • 原碼:二進制數(shù)據(jù)的最高位用來作為符號位,1表示負數(shù),0表示正數(shù),剩余位來表示這個數(shù)據(jù)的數(shù)值大小(絕對值),也就是說,負數(shù)的原碼是在其絕對值原碼的基礎(chǔ)上將最高位變成0。原碼的表示簡單易懂,正負數(shù)區(qū)分方便且易于轉(zhuǎn)換,但是在實際用于計算時卻不太方便,當兩個正數(shù)做減法運算,或者兩個異號的數(shù)相加時,必須先比較兩個數(shù)的絕對值大小才能進行減法運算,以便于決定最終結(jié)果是正號還是負號。所以,原碼表示數(shù)據(jù)時不便于做加減運算。
  • 反碼:正數(shù)的反碼與原碼相同;負數(shù)的反碼是在負數(shù)的原碼基礎(chǔ)上,符號位不變,其它位全部取反。反碼的存在一般是為了方便計算補碼。
  • 補碼:對正數(shù)來說,原碼、反碼、補碼是完全一致的;對負數(shù)來說,補碼是在其反碼的基礎(chǔ)上將整個數(shù)加1。在計算機系統(tǒng)中,所有的數(shù)值一律用補碼的形式來存儲。補碼的存在主要有這幾種意義:
    • 統(tǒng)一0的編碼。不管是用原碼還是反碼來表示0,都會有兩種表示方式,即正0和負0,但是我們知道,0不區(qū)分正負。這就導致同一個數(shù)值0出現(xiàn)兩種表示方式,而使用補碼表示時,對于正0,原碼為00000000,反碼為00000000,補碼為00000000;對于負0,原碼為10000000,反碼為11111111,補碼為11111111+1=00000000,其中最高位(第九位)數(shù)字1被舍棄。這樣,正0和負0的補碼就一樣了。
    • 便于運算。使用補碼進行運算時可以將減法轉(zhuǎn)化為加法,對于任何數(shù)的加減運算,都直接使用補碼進行加法運算即可,并且可以將符號位和其他位統(tǒng)一處理,當兩個用補碼表示的數(shù)相加時,如果最高位(符號位)有進位,則進位直接舍棄。

unsigned:聲明無符號類型變量。

數(shù)據(jù)類型占用空間取值范圍
short2字節(jié)-32768 到 32767 (-2^15 ~ 2^15-1)
int4字節(jié)-2147483648 到 2147483647 (-2^31 ~ 2^31-1)
long4字節(jié)-2147483648 到 2147483647 (-2^31 ~ 2^31-1)
unsigned short2字節(jié)0 到 65535 (0 ~ 2^16-1)
unsigned int4字節(jié)0 到 4294967295 (0 ~ 2^32-1)
unsigned long4字節(jié)0 到 4294967295 (0 ~ 2^32-1)

struct:聲明結(jié)構(gòu)體變量。

數(shù)組是相同類型數(shù)據(jù)的集合,而結(jié)構(gòu)體可以把不同的數(shù)據(jù)組合成一個整體。通過結(jié)構(gòu)體,我們可以把大量的不同類型數(shù)據(jù),甚至是函數(shù)和其他復合類型數(shù)據(jù)打包為一個整體。在使用struct關(guān)鍵字時,應區(qū)分開結(jié)構(gòu)體類型和結(jié)構(gòu)體變量的區(qū)別,聲明結(jié)構(gòu)體類型并不會分配內(nèi)存,只有在定義結(jié)構(gòu)體類型的時候才會分配內(nèi)存。通常struct關(guān)鍵字會和typedef關(guān)鍵字一塊使用,通過別名的方式可以在定義結(jié)構(gòu)體變量時不需要再寫struct關(guān)鍵字。

struct st
{int a;char b;
}; //聲明結(jié)構(gòu)體類型
struct st s_val = {1, 'a'}; //定義結(jié)構(gòu)體變量,分配內(nèi)存//定義結(jié)構(gòu)體變量時不能省略struct關(guān)鍵字typedef struct st
{int a;char b;
}_st; //給結(jié)構(gòu)體類型取別名為_st
_st val = {1, 'a'}; //可以不寫struct

結(jié)構(gòu)體變量所占的存儲空間大小是所有結(jié)構(gòu)體成員所占存儲空間大小的總和,并且需要考慮內(nèi)存對齊方式。而且,空結(jié)構(gòu)體(沒有任何成員)也是占存儲空間的,空結(jié)構(gòu)體占1字節(jié)存儲空間。

在結(jié)構(gòu)體中可以包含一種稱為柔性數(shù)組的成員,柔性數(shù)組是一個未知大小的數(shù)組,它必須是結(jié)構(gòu)體的最后一個成員,并且柔性數(shù)組成員的前面必須有一個其他成員。

struct st
{int val;int arr[0]; //int arr[];
};

這個0長度的數(shù)組成員arr是不占存儲空間的,這個結(jié)構(gòu)體的大小為4字節(jié)。有了這個0長度數(shù)組我們便可以方便的擴展這個結(jié)構(gòu)體的大小了

struct st *p_st = (struct st *)malloc(sizeof(struct st) + 10 * sizeof(int));

如上,我們使用包含0長度數(shù)組的結(jié)構(gòu)體類型定義一個結(jié)構(gòu)體指針,并通過malloc在堆上為其分配一塊內(nèi)存,這塊內(nèi)存的大小為44字節(jié),而結(jié)構(gòu)體類型大小只有4字節(jié),但是我們卻可以像訪問普通數(shù)組一樣通過p_st[i]來訪問這塊內(nèi)存。也就是說,柔性數(shù)組并不是結(jié)構(gòu)體類型的成員,但是通過結(jié)構(gòu)體成員卻可以訪問我們自定義的柔性數(shù)組存儲空間。

最后,在C++中,struct結(jié)構(gòu)體和class類的區(qū)別,struct成員默認是public屬性,而class的成員默認是private屬性。

同樣,在C語言中也可以實現(xiàn)C++面向?qū)ο蟮男Ч?#xff0c;使用struct結(jié)構(gòu)可以實現(xiàn)封裝,而結(jié)構(gòu)體做結(jié)構(gòu)體成員又可以實現(xiàn)C++中的繼承,并且,函數(shù)指針做結(jié)構(gòu)體成員可是模仿C++類中的方法。

union:聲明聯(lián)合數(shù)據(jù)類型。

聯(lián)合union是一個能在同一個存儲空間存儲不同類型數(shù)據(jù)的類型,也就是說,union的所有成員共享同一塊存儲空間,同一存儲空間段可以用來存放幾種不同類型的成員,但每一時刻只有一種起作用。聯(lián)合體所占的存儲空間長度為占用存儲空間最大的成員的長度,所以也叫做共用體。共用體變量中起作用的成員是最后一次存放的成員,在存入一個新的成員后原有的成員的值會被覆蓋。并且,共用體變量的地址和它的各成員的地址都是同一地址。

一個union變量只分配一個足夠大的存儲空間能夠存儲最大長度的成員,而不會給每一個成員都分配內(nèi)存,這是union與struct最大的區(qū)別。union主要用來達到節(jié)省空間的目的,和struct一樣,在C++中,union的成員默認屬性為public。

看下面的例子

typedef union
{int data;char buf[2];
}u_t;int main()
{u_t* p, u;memset(&u, 0, sizeof(u));p = &u;p->buf[0] = 0x12;p->buf[1] = 0x34;printf("%x\n", p->data);return 0;
}

對union成員的訪問也需要考慮大端存儲模式和小端存儲模式。

enum:聲明枚舉類型。

通過enum枚舉類型可以定義枚舉變量,該枚舉變量的值只能是枚舉類型中列舉出來的那些值。

enum  枚舉名
{枚舉值表
};

枚舉值表中的所有可用值是枚舉變量可以使用的值,也成為枚舉元素。枚舉值是常量,在程序中枚舉值不能作為左值(不能給枚舉值使用賦值語句賦值)。另外,枚舉元素本身由系統(tǒng)定義了一個表示序號的數(shù)值從0開始順序定義為0,1,2 …依次遞增,我們也可以顯示的給枚舉元素賦值。

enum day
{mom = 1,tue,	//2wed,	//3fri = 5,sat,	//6sun		//7
};

我們知道使用宏定義#define也可以定義常量,但是宏定義常量和枚舉常量是有區(qū)別的,#define 宏常量是在預編譯階段進行簡單替換,而枚舉常量則是在編譯的時候確定其值。

void:聲明空類型指針(void類型指針可以接受任何類型指針的賦值,無需類型轉(zhuǎn)換),聲明函數(shù)無返回值或無參數(shù)等。

void主要的用途是限制函數(shù)的返回值或者函數(shù)參數(shù)。在C語言中,如果一個函數(shù)不加返回值類型限定,那么編譯器會默認該函數(shù)返回整型值,所以,當一個函數(shù)沒有返回值的時候,一定要聲明為void類型。當函數(shù)沒有參數(shù)時,也應該聲明為void。實際上,在C++中函數(shù)參數(shù)為void表示該函數(shù)不接受任何參數(shù),如果調(diào)用該函數(shù)時添加了參數(shù)那么會報錯;而C語言中,參數(shù)為void的函數(shù)可以接受任何類型的參數(shù)。為了統(tǒng)一,無論C還是C++,只要函數(shù)沒有參數(shù),都要顯式指明參數(shù)為void。

void類型指針可以指向任何類型的內(nèi)存塊,但是使用void類型指針的時候要格外注意。在ANSI標準中,不允許對void類型指針進行加減操作,這是因為指針的步長是由指針的類型決定的。比如

int *p = 0xaa;
p++; //指針類型為int,每次加一移動4字節(jié)

這里int類型的指針每次自加一會移動4字節(jié),因為int類型的對象占據(jù)的存儲空間就是4字節(jié)。而void類型的指針在移動時你并不知道它指向的存儲空間的大小。但是在GNU標準中是允許對void類型指針進行加減操作的。為了統(tǒng)一,我們可以在對void類型指針進行加減操作時強制類型轉(zhuǎn)換,以此來說明指針移動步長。

void *p;
(int *)p++;

對于函數(shù)來說,如果函數(shù)的參數(shù)可以是任意類型指針,那么可以將函數(shù)參數(shù)聲明為void*類型,比如典型的C語言內(nèi)存操作函數(shù)memset和memcpy函數(shù),內(nèi)存操作函數(shù)所操作的對象是一塊內(nèi)存本身,本就不應該關(guān)心這塊內(nèi)存是什么類型,只要我們通過函數(shù)參數(shù)告訴編譯器我們要操作的這塊內(nèi)存的大小就行了,這也是C語言內(nèi)存操作函數(shù)的精髓所在,并且也體現(xiàn)了作為一個內(nèi)存操作API的統(tǒng)一性。比如

int buf[20];
memset(&buf, 0, 20 * (sizeof(int)));

這句代碼的意思是把buf這個數(shù)組清0,我們只要把buf這塊內(nèi)存的首地址傳給memset函數(shù),并將要清0的這塊內(nèi)存的大小通過參數(shù)傳入就可以了。

最后,void是一種抽象,可以參考C++中的抽象類來理解。抽象類不能實例化,同樣我們也不能去定義一個void類型的變量,因為在定義變量時,編譯器要為變量分配內(nèi)存,而void類型本身就是一種抽象,編譯器不知道分配多大內(nèi)存給這個變量。通常,void類型用于定義一個可以指向任何類型內(nèi)存塊的指針。

2. 控制語句關(guān)鍵字(12個)

if:條件語句。

else:條件語句中的否定分支,在if后使用或作為else if分支。

switch:開關(guān)語句。

case:開關(guān)語句分支。

case后面的值只能是整型或字符型的常量或者常量表達式。當有較多的case選項時,應該盡量把出現(xiàn)概率更大的case選項放在前面,以提升程序的執(zhí)行效率。

default:開關(guān)語句中的其他分支。

for:循環(huán)語句。

do:循環(huán)語句中的循環(huán)體。

while:循環(huán)語句中的條件。

break:跳出循環(huán)。

continue:跳出本次循環(huán),進入下一次循環(huán)。

goto:無條件跳轉(zhuǎn)。

return:返回語句,可帶參數(shù)。

return用來終止一個函數(shù),并將return后面的值返回給函數(shù)的返回值。在函數(shù)內(nèi)部,當執(zhí)行到return語句的時候就會終止這個函數(shù),并返回值,return語句后面的程序?qū)⒉粫俦粓?zhí)行。

return返回的值不能是存儲在棧上的值(局部變量),因為局部變量在這個函數(shù)結(jié)束的時候被自動銷毀,它的生命周期僅限于這個函數(shù)內(nèi)部,所以不能作為return語句的返回值。

3. 存儲類關(guān)鍵字(5個)

auto:聲明自動變量,缺省時編譯器默認為auto。

默認情況下,缺省時所有變量都是auto的。

extern:聲明外部變量。

extern表示外部的,通過extern聲明的變量或函數(shù)表示該變量或者函數(shù)是在外部文件定義的,告訴編譯器在本文件中遇到該變量或者函數(shù)時,去其他文件中尋找變量或函數(shù)的定義。

register:聲明寄存器變量。

定義寄存器變量,提高效率。register是建議型的指令,而不是命令型的指令,如果CPU有空閑寄存器,那么register就生效,如果沒有空閑寄存器,那么register無效。該關(guān)鍵字請求編譯器盡量的將變量存放在CPU內(nèi)部寄存器中,這樣在訪問變量時不需要再通過內(nèi)存尋址的方式訪問,而是直接在寄存器中訪問,大大提升了訪問速度。但是CPU內(nèi)部寄存器是有限的,所以register關(guān)鍵字只能是盡可能的請求編譯器把變量存放在寄存器,而不是一定存放在寄存器。因為register關(guān)鍵字用于請求將數(shù)據(jù)存放在寄存器,所以使用register修飾符來修飾的變量必須是能被CPU寄存器所接受的類型,即register修飾的變量必須是長度小于或等于整形長度的值。同時,因為register修飾的變量可能會存放在寄存器中(也可能存放在內(nèi)存中),所以不能對register修飾的變量進行取址操作,即不能通過取址操作符&來獲取register修飾變量的地址。

static:聲明靜態(tài)變量。

  • 修飾變量

    static關(guān)鍵字可以修飾全局變量和局部變量,并且他們都會被存放在內(nèi)存的靜態(tài)區(qū)。

    • 靜態(tài)全局變量:限定變量的作用域為當前文件,即從變量定義之處開始一直到當前文件末尾,當前文件中該變量定義之前也無法使用(除非加extern聲明),其他文件中即便是使用extern聲明也無法使用。
    • 靜態(tài)局部變量:定義在函數(shù)體內(nèi)部,并且作用域僅限于當前函數(shù),當前文件該函數(shù)體外部無法使用。因為static修飾的靜態(tài)變量存放在內(nèi)存的靜態(tài)區(qū),所以函數(shù)運行結(jié)束這個靜態(tài)變量也不會被銷毀,函數(shù)下次被調(diào)用時這個變量的值依然存在,也就是我們說的靜態(tài)局部變量只能被初始化一次,并且有記憶功能,下次調(diào)用函數(shù)時可以使用上次函數(shù)調(diào)用結(jié)束時靜態(tài)局部變量的值。需要注意的是,普通的局部變量存放在棧區(qū),函數(shù)調(diào)用結(jié)束變量就會被析構(gòu),也就是說普通局部變量的聲明周期為定義該變量的函數(shù)體內(nèi)。而靜態(tài)局部變量存放在靜態(tài)區(qū),它的生命周期是整個程序執(zhí)行期間,也就是說定義該靜態(tài)局部變量的函數(shù)執(zhí)行完畢,并不會析構(gòu)靜態(tài)局部變量,而是在當前程序執(zhí)行完畢才會析構(gòu)。
  • 修飾函數(shù)

    使用static關(guān)鍵字修飾函數(shù)可以將函數(shù)變?yōu)殪o態(tài)函數(shù),也成為內(nèi)部函數(shù),靜態(tài)函數(shù)的作用域為當前文件,在該文件之外無法訪問。使用靜態(tài)函數(shù)的好處是可以避免不同文件中函數(shù)同名引起的錯誤,但是會導致該文件之外無法調(diào)用的問題。

const:聲明只讀變量(C和C++區(qū)別)。

在C語言中,const定義的并不是真正的常量,而是具有只讀屬性的變量,其本質(zhì)還是變量,只不過不可修改(實際上在C語言中是可以通過指針等其他方式間接修改的);而在C++中,const定義的是真正的常量,C++中是通過符號表一一對應的方式實現(xiàn)的。通過下面的例子也可以證明

const int NUM = 10;
char buf[NUM];

上面代碼在C語言中編譯不通過,但是在C++中編譯通過。我們知道,定義數(shù)組時要指定數(shù)組大小,以便于編譯器分配內(nèi)存。在C語言中編譯不通過也就證明了const定義的依然是變量,而不是常量。

編譯器通常不會為const只讀變量分配存儲空間,而是將它們保存在符號表中,這使得它們成為一個編譯期間的值,沒有讀寫內(nèi)存的操作,大大提高了效率。另外需要注意const與宏#define的區(qū)別

#define NUM 1 		//宏定義一個常量
const int VAL = 2; 	//還沒有將VAL放入內(nèi)存中
int a = VAL; //此時為VAL分配內(nèi)存,后面不再分配內(nèi)存
int b = NUM; //預編譯期間進行宏替換,分配內(nèi)存
int c = VAL; //不會分配內(nèi)存
int d = NUM; //宏替換,還會分配內(nèi)存

從匯編的角度來看,const定義的只讀變量只是給出了內(nèi)存地址,而#define給出的是立即數(shù)。所以,在程序運行過程中,const定義的只讀變量只有一份拷貝(全局只讀變量存放在靜態(tài)區(qū),而不是堆棧),而#define定義的常量在內(nèi)存中有多份拷貝。#define在預編譯的時候進行宏替換,而const只讀變量是在編譯時確定它的值。另外,#define定義的常量沒有類型,而const修飾的只讀變量是有類型的。const 修飾的只讀變量不能用來作為定義數(shù)組的維數(shù),
也不能放在case 關(guān)鍵字后面。

最后,當const修飾指針時,放在不同位置所代表的含義也不同。

const int *p;			//const修飾指針指向的內(nèi)存,//指針本身可變,指針指向的內(nèi)存不可修改
int const *p;			//const修飾指針指向的內(nèi)存,//指針本身可變,指針指向的內(nèi)存不可修改int * const p;			//const修飾指針本身,//指針指向不可修改,指針指向的內(nèi)存可以修改const int const *p;		//指針本身和指針指向的內(nèi)存都不可修改

4. 其他關(guān)鍵字(3個)

sizeof:計算一個對象所占的字節(jié)數(shù)。

sizeof在使用時雖然會加括號,但是他并不是函數(shù),而是一個關(guān)鍵字。實際上,通過sizeof計算一個變量所占的內(nèi)存大小時可以省略括號,sizeof(val)和sizeof val都可以,但是在計算數(shù)據(jù)類型的大小時必須加括號sizeof(int),否則的話會和類型擴展混淆,比如unsigned int就是擴展為無符號整型變量。因為sizeof不是函數(shù),所以在使用時不需要包含任何頭文件,但是sizeof是有返回值的,范圍值類型為size_t,在32位操作系統(tǒng)下是unsigned int類型。

在計算一個字符串變量的大小時要區(qū)分sizeof與strlen的區(qū)別,strlen是一個函數(shù),用于計算字符串的長度,所以不包含字符串最后的’\n’,而sizeof是計算變量所占內(nèi)存大小,包括字符串結(jié)束符’\n’。

typedef:取別名。

typedef可以為一個數(shù)據(jù)類型定義一個新的名字,但是不能創(chuàng)建一個新的類型。與#define不同,typedef僅限于為數(shù)據(jù)類型取別名,而不能為表達式或具體的值取別名。#define發(fā)生在預處理階段,typedef發(fā)生在編譯階段。

volatile:防止編譯器優(yōu)化,說明變量在程序執(zhí)行中可被隱含地改變。

volatile是易變的意思,它修飾的變量表示該變量的值可能被某些因素所修改,比如操作系統(tǒng)、硬件外設(shè)或其他線程等等。volatile關(guān)鍵字修飾的變量,編譯器不會對改變量進行優(yōu)化訪問。

當我們讀取一個普通變量的值時,編譯器為了加快訪問速度,一般會在緩存中讀取該變量的值,而不是直接去寄存器取值。但是,有時候寄存器的值并不是通過程序去修改的,比如嵌入式開發(fā)中常用開發(fā)板進行開發(fā),很多時候寄存器的值會被芯片的外設(shè)所修改。這時候,雖然我們程序中并沒有去修改寄存器的值,但是寄存器值卻因為外界因素而發(fā)生了改變。當我們?nèi)ピL問這種變量的時候,如果不加volatile關(guān)鍵字,編譯器默認會在緩存中取值,而此時緩存中的值是一個舊值,變量的真實值已經(jīng)發(fā)生了改變。所以,加volatile關(guān)鍵字就是為了告訴編譯器,不要對訪問進行優(yōu)化,每次都應該去變量的地址處去訪問變量值,以此來確保每次取到的都是變量的最新值。

下面通過例子說明

int val = 1;
int a = val;
int b = val;

在上面的代碼中,變量val沒有被用作左值(也就是說在程序中變量val的值沒有被顯式改變),這時候編譯器就會認為變量val的值沒有發(fā)生過改變,并會對val的訪問做優(yōu)化處理。當給變量a賦值時,編譯器取到val的值之后賦給a,并且這個值會被放到緩存中。當給b賦值時,因為編譯器認為val的值沒有發(fā)生改變,所以會直接在緩存中取val的值,而不會去val變量的地址處取值,這樣大大提高了訪問速度。這么做的前提是,兩次訪問val的語句之間沒有將val當左值的語句(即修改val值的語句)。

如果說將val變量修飾為volatile變量,那就不同了。

volatile int val = 1;
int a = val;
int b = val;

此時,編譯器認為val的值是隨時可能發(fā)生改變的,不管程序中有沒有將val當作左值的語句,每次訪問val變量都會區(qū)val變量的地址處去訪問。也就是說,在給a賦值時,編譯器將會在val地址處取值,當給b賦值時,編譯器依然會去val變量的地址處取值。

一般來說,對寄存器變量、端口數(shù)據(jù)變量、多線程共享數(shù)據(jù)變量使用volatile修飾可以保證對變量真實值的穩(wěn)定訪問。


在這里插入圖片描述
在這里插入圖片描述


http://www.risenshineclean.com/news/60722.html

相關(guān)文章:

  • 搭建cms網(wǎng)站網(wǎng)絡(luò)互聯(lián)網(wǎng)推廣
  • 廣東兩學一做網(wǎng)站西安網(wǎng)是科技發(fā)展有限公司
  • 江門模板建站哪家好網(wǎng)站推廣網(wǎng)絡(luò)營銷方案
  • 網(wǎng)站里的橫幅怎么做項目網(wǎng)站
  • 鄭州網(wǎng)站建設(shè)哪家好打開百度一下網(wǎng)頁版
  • 青之峰做網(wǎng)站廈門seo新站策劃
  • 臨清網(wǎng)站制作公司plc培訓機構(gòu)哪家最好
  • 創(chuàng)建公司策劃書寧波優(yōu)化推廣選哪家
  • 網(wǎng)站建站方案說明書網(wǎng)站制作的費用
  • 哪家上市公司做視頻網(wǎng)站培訓機構(gòu)專業(yè)
  • wordpress導航目錄手機優(yōu)化大師為什么扣錢
  • 天津制作企業(yè)網(wǎng)站提高工作效率的方法
  • 惠州哪家做網(wǎng)站比較好百度seo如何做
  • 做網(wǎng)站備案與不備案的區(qū)別seo長尾關(guān)鍵詞優(yōu)化
  • 重慶所有做網(wǎng)站的公司包頭網(wǎng)站建設(shè)推廣
  • 商城網(wǎng)站建設(shè)-公司網(wǎng)絡(luò)營銷推廣軟件
  • 網(wǎng)站建設(shè)管理的規(guī)章制度新產(chǎn)品怎樣推廣
  • 廣告商對接平臺百度seo網(wǎng)站優(yōu)化
  • 如何讓百度快速收錄網(wǎng)站惠州百度關(guān)鍵詞優(yōu)化
  • 俄羅斯網(wǎng)站建設(shè)公司網(wǎng)頁開發(fā)需要學什么
  • 學校做網(wǎng)站有些什么好處在什么網(wǎng)站可以免費
  • 電商網(wǎng)站建設(shè)技術(shù)交流問題2023年的新聞時事熱點論文
  • 上海網(wǎng)站建設(shè)seo1888百度快速收錄技術(shù)
  • 哪幾個網(wǎng)站做acm題目最近幾天發(fā)生的新聞大事
  • 網(wǎng)站建設(shè)費用 優(yōu)幫云杭州做seo的公司
  • 朝陽專業(yè)網(wǎng)站建設(shè)靜態(tài)網(wǎng)頁設(shè)計與制作
  • 交城有做網(wǎng)站的嗎品牌營銷是什么
  • wordpress支付文件在哪seo網(wǎng)上培訓課程
  • 怎么制作黃色網(wǎng)站中國北京出啥大事了
  • 怎么增加網(wǎng)站的外鏈網(wǎng)站流量分析工具