找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1912|回復: 0
打印 上一主題 下一主題
收起左側(cè)

C語言關(guān)鍵字解析

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-6 03:02 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本帖最后由 51黑tt 于 2016-3-6 03:03 編輯

C語言關(guān)鍵字有32個,如表1所示。雖然簡單,但還是讓一些初學者犯錯,譬如sizeof,好多初學者都認為是函數(shù),其中包括我的一些同學,他們學過有好多年了,如此看來,有時我們追求高深的內(nèi)容,往往會忽略基礎(chǔ)的簡單的內(nèi)容!
表1 C語言標準定義的 32個關(guān)鍵字
關(guān)鍵字 意義
auto 聲明自動變量,缺省時編譯器一般默認為 auto
int 聲明整型變量
double 聲明雙精度變量
long 聲明長整型變量
char 聲明字符型變量
float 聲明浮點型變量
short 聲明短整型變量
signed 聲明有符號類型變量
unsigned 聲明無符號類型變量
struct 聲明結(jié)構(gòu)體變量
union 聲明聯(lián)合數(shù)據(jù)類型
enum 聲明枚舉類型
static 聲明靜態(tài)變量
switch 用于開關(guān)語句
case 開關(guān)語句分支
default 開關(guān)語句中的“其他”分支
break 跳出當前循環(huán)
register 聲明寄存器變量
const 聲明只讀變量
volatile 說明變量在程序執(zhí)行中可被隱含地改變
typedef 用以給數(shù)據(jù)類型取別名(當然還有其他作用)
extern 聲明變量是在其他文件正聲明(
return 子程序返回語句(可以帶參數(shù),也可不帶)
void 聲明函數(shù)無返回值或無參數(shù),聲明空類
continue 結(jié)束當前循環(huán),開始下一輪循環(huán)
do 循環(huán)語句的循環(huán)體
while 循環(huán)語句的循環(huán)條件
if 條件語句
else 條件語句否定分支(與 if 連用)
for 一種循環(huán)語句
goto 無條件跳轉(zhuǎn)語句
sizeof 計算對象所占內(nèi)存空間大小
在這里我們也不一一講解每個關(guān)鍵字,只是講講比較容易被人忽略的或者易出錯的關(guān)鍵字說明一下。
在講之前,先說明一下,定義和聲明的區(qū)別:
定義:編譯器在創(chuàng)建一個對象時,為該對象申請開辟的內(nèi)存空間,這個空間的的名字就是變量名或者對象名。同一個變量名在摸個區(qū)域內(nèi)只能定義一次,重復定義會出現(xiàn)錯誤的。
聲明:有兩種作用,
1. 告訴編譯器,這個變量或者函數(shù),我已經(jīng)定義了(開辟空間了),但是在別的地方,我先說明一下,免得編譯器報錯。當然,聲明可以多次出現(xiàn)。
2. 告訴編譯器,這個變量名或者對象名,我先預定了,其他地方不可以用了。和在飯館吃飯(人多)要提前預約一樣的道理。
定義和聲明最本質(zhì)的區(qū)別在于,聲明沒開辟空間,而定義則創(chuàng)建對象(變量)并開辟了空間。這是最重要的一點。
一. auto,register,extern,static,四種關(guān)鍵字
C語言說明變量的時,同時給出了兩個方面的信息:數(shù)據(jù)類型和存儲類。C語言中提供了存儲說明符auto,register,extern,static說明的四種存儲類別。
1. auto 是變量是C語言最常用的。編譯器在默認的缺省情況下,所有變量都是auto的。對于函數(shù)的形參,也是auto型的。
2. extern, 語言中存在這樣的一種變量,在一個函數(shù)中合法出現(xiàn)的同時,又可以在其他的函數(shù)中合法出現(xiàn),這就是外部變量。它的生命周期是整個程序的執(zhí)行周期。
3. register,寄存器變量,其值存放在寄存器中,訪問速度快。有最快的關(guān)鍵字的稱呼。雖然寄存器的速度非常快,但是使用 register修飾符也有些限制的:register變量必須是能被 CPU寄存器所接受的類型。意味著 register變量必須是一個單個的值,并且其長度應小于或等于整型的長度。而且register變量可能不存放在內(nèi)存中, 所以不能用取址運算符 “&”來獲取 register變量的地址。
4. static 靜態(tài)變量,兩個作用。第一個作用:修飾變量,都存在內(nèi)存的靜態(tài)區(qū)。
靜態(tài)局部變量:出現(xiàn)在函數(shù)體內(nèi),生命周期是整個程序的執(zhí)行過程,由于被 static修飾的變量總是存在內(nèi)存的靜態(tài)區(qū),即使該函數(shù)生命結(jié)束,其值不會被銷毀,同樣要修改該變量,就要到函數(shù)內(nèi)部完成,所以用起來比較安全,起到信息屏蔽的作用。
靜態(tài)全局變量:出現(xiàn)在函數(shù)體外,作用域僅限于變量被定義的文件中,其他文件即使用 extern聲明也沒法使用他。
第二個作用,修飾函數(shù),函數(shù)前加 static使得函數(shù)成為靜態(tài)函數(shù)。但此處“static”的含義不是指存儲方式,而是指對函數(shù)的作用域僅局限于本文件(所以又稱內(nèi)部函數(shù))。使用內(nèi)部函數(shù)的好處是:不同的人編寫不同的函數(shù)時,不用擔心自己定義的函數(shù),是否會與其它文件中的函數(shù)同名。
二. 基本數(shù)據(jù)類型----short、int、 long、char、float、double
這些關(guān)鍵字都是基本的數(shù)據(jù)類型,每種類型占據(jù)的內(nèi)存空間不一樣,其實每種類型相當于一個模型,再通俗點就是一個模子。具體占多少個字節(jié),可以用關(guān)鍵字sizeof去測一下。另外就就是存儲問題。不論是float還是double在存儲方式上都遵從IEEE的規(guī)范,float遵從的是IEEE R32.24 ,而double 遵從的是R64.53。
#include"stdio.h"
int main()
{
    float a=999.999;
    float b=0.005;
    printf("%lf\n",a+b-1000.004);
    return 0;
}
看看得到的結(jié)果并不是0,按數(shù)學計算本來應該是0,但由于浮點數(shù)的存儲有微小的誤差從而導致計算結(jié)果不是0
double m=3.3;
cout<<m;</m;
你輸入3.3,再調(diào)試監(jiān)測m的值你會發(fā)現(xiàn)存儲的是3.2999999999999998,而不是3.3.這就是本來是3.3而經(jīng)過存儲卻變的不是3.3.
對計算機來說,實數(shù)是不存在的東西。一般,計算機除了認識“整數(shù)”——這個整數(shù)和數(shù)學中的整數(shù)也不是一個東西。
還認識的一種數(shù)就是“浮點數(shù)”——和數(shù)學中的實數(shù)更是兩碼事。
三.最冤枉的關(guān)鍵字sizeof
經(jīng)常被我們當成函數(shù)來使用,雖然造型很像函數(shù),其實是關(guān)鍵字,
int i=0;
A),sizeof(int); B),sizeof(i); C),sizeof int; D),sizeof i;
以上四種寫法都是正確的,結(jié)果為4.可以在VC6.0編譯器watch窗口下觀察,前兩種寫法很常見,但后面的也正確。從c和d正確可以排除sizeof是函數(shù)的說法,當然我們在使用的時候還是加上括號,披著函數(shù)皮的關(guān)鍵字吧!
請看下面的例子:
struct Test
{       int Num;
        char*Pc;
        short sDtate;
        char ch[2];
        short S[4];
}*p;
那么這個結(jié)構(gòu)體的大小多少呢?他與共同體的區(qū)別很明顯,共同體所有成員變量都共用同一塊內(nèi)存,而結(jié)構(gòu)體每個元素都占用相應地內(nèi)存。
共同體的最大的成員所占內(nèi)存為共同體占用內(nèi)存。
int:占4個字節(jié)(32系統(tǒng))。
char*pc:4個:指針相當于地址,地址就是你當前操作系統(tǒng)的位數(shù)。如果是指針數(shù)組即存放指針的數(shù)組,占用的空間是4*數(shù)組的個數(shù)。
如果是數(shù)組指針即指向數(shù)組的指針,指針指向的是數(shù)組的地址,占用4個字節(jié)。
short sDtate:2個
char ch[2]:2個
short S[4]:2*4=8 short型數(shù)組
所以一起:4+4+2+2+8=20字節(jié)。VC下驗證是正確的,不要以為這樣就沒事了,其實還是有問題的:字節(jié)對齊的問題。
struct S1
{
char c;
int i;
};
S1 s1={'a',0xFFFFFFFF};
問sizeof(s1)等于多少?char占1個字節(jié),int占4個字節(jié),那么加起來就應該是5。這樣算對嗎?VC6中按默認設(shè)置得到的結(jié)果卻是為8。
我們來好好琢磨一下sizeof的定義——sizeof的結(jié)果等于對象或者類型所占的內(nèi)存字節(jié)數(shù),好吧,那就讓我們來看看S1的內(nèi)存分配情況:
以我的VC6.0為例,s1的地址為0x0012FF74,使用memory窗口觀察,其數(shù)據(jù)內(nèi)容如下:
0012FF74: 61 CC CC CC FF FF FF FF
你會發(fā)現(xiàn)中間夾雜了3個字節(jié)的CC?看看MSDN上的說明:
When applied to a structure type or variable, sizeof returns the actual size,which may include padding bytes inserted for alignment.
原來如此,這就是傳說中的字節(jié)對齊!那么為什么需要字節(jié)對齊?計算機組成原理教導我們這樣有助于加快計算機的取數(shù)速度,否則就得多花指令周期了。各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取。其他平臺可能沒有這種情況, 但是最常見的是如果不按照適合其平臺的要求對數(shù)據(jù)存放進行對齊,會在存取效率上帶來損失。這也是空間和時間的博弈。



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表