當對乙個變數頻繁被讀寫時,需要反覆訪問記憶體,從而花費大量的訪問時間。為此,c語言提供了一種變數,即暫存器變數。這種變數存放在cpu的暫存器中,使用時,不需要訪問記憶體,而直接從暫存器中讀寫,從而提高效率。暫存器變數的說明符是register。對於迴圈次數較多的迴圈控制變數及迴圈體內反覆使用的變數均可定義為暫存器變數,而迴圈計數是應用暫存器變數的最好候選者。
(1) 只有區域性自動變數和形參才可以定義為暫存器變數。因為暫存器變數屬於動態儲存方式,凡需要採用靜態儲存方式的量都不能定義為暫存器變數,包括:模組間全域性變數、模組內全域性變數、區域性static變數;
(2) register是乙個"建議"型關鍵字,意指程式建議該變數放在暫存器中,但最終該變數可能因為條件不滿足並未成為暫存器變數,而是被放在了儲存器中,但編譯器中並不報錯(在c++語言中有另乙個"建議"型關鍵字:inline)。
分析下列**的輸出結果:
int array[10]
=;0[array]=1
;printf
("%d",(
-5)[array+5]
);
結果是輸出:1
因為array[2]可以看作*(array+2)
,所以(-5)[array+5]
就相當於*(-5+array+5)
,也就是*(array+0)
。
所以,盡量使用指標代替陣列, 指標方法的優點是,array的位址每次裝入位址p後,在每次迴圈中只需對p增量操作。在陣列索引方法中,每次迴圈中都必須進行基於t值求陣列下標的複雜運算 。
static是c的乙個關鍵字,根據其修飾的物件屬性不同可以分為兩種用途:
1.修飾儲存型別,使之成為靜態儲存型別
2.修飾鏈結屬性,使之成為內部鏈結屬性
靜態儲存型別:
當修飾在函式內部定義的區域性變數時,這個區域性變數就儲存在函式的記憶體靜態區,函式執行結束後也不會銷毀這個區域性變數的值,函式下次執行的時候依然可以使用上次執行後的變數的值。
當修飾全域性變數的時候,此時的全域性變數就是靜態全域性變數,該變數的作用域只能夠限制在定義該變數的檔案中,而且其他檔案不能夠通過extern關鍵字來引用。
靜態函式只能在宣告它的原始檔中使用 。
例子:
判斷如下程式輸出的值:
char c[
8]=;
printf
("%d,"
,sizeof
(c))
;printf
("%d"
,strlen
(c))
;
這涉及到sizeof和strlen的區別:
所以對於
char c[
8]=;
圖示:
const具有左結合性,即通常:const + 修飾變數
對於const的用法,程式如下:
int tmp =66;
int*
const age =
&tmp;
int newage =
23;
執行的語句如下:
*age=newage;
age =
&newage;
問題:判斷哪個語句是正確的,為什麼?
分析:第一條**:建立乙個int型變數tmp,並且初始化66
第二條**:建立乙個int型指標age,指向tmp變數,age中的值就是tmp的位址,const具有左結合性,所以const修飾的是age,即指標的指向不變,始終指向tmp的位址
第三條**:建立乙個int型變數newage,並且初始化23
第二條語句:age = &newage; 表示改變age的指向,使age指向newage變數的位址,由於const修飾了age,也就是指標的指向,所以指向不可改變,第二條指令錯誤!!!
關於指標的要點分析:下列**的執行結果是什麼:我們要明白定義乙個指標變數時,int
* p;
* 和 p
分別代表這什麼
*
是取值運算子,所以*p
代表指標指向的位址中的值;
p
代表指標指向的位址;
&p
代表指標的位址;
*&p
代表指標位址中的值,也就是指標指向的位址
int
*p;int a =8;
*p = a;
printf
("%d"
,*p)
;
執行結果如下:
分析:雖然宣告了p指標,但是沒有說明p指向哪個記憶體位置,所以p就是乙個野指標,對野指標執行*p=a
後就會報錯。
野指標形成的三種原因:
1.指標變數沒有初始化,所有指標在建立的時候不會被自動初始化為null的,預設值是隨機指向的;
2.當指標被free或者delete之後,沒有指向null,會不小心再次使用;
3.指標的操作超過了指標的作用範圍,比如不要返回指向棧記憶體的指標,因為在函式結束時棧記憶體會被釋放。
解決方法:
int a =9;
int*p=
&a;//初始化的時候就指向a變數的位址
printf
("%d\n"
,*p)
;
問題:
如何輸出原始檔和當前執行的行數?寫乙個程式來實現。
分析:
要注意的是,巨集定義左右都是雙下劃線!!!
**如下:
#include
"stdio.h"
intmain
(void
)
執行結果如下:
分析下面**,求執行結果:
int a =20;
if(1<=a<=10)
else
主要考察的是if( 1<=a<=10 )
的判斷結果,由於是判斷語句,所以結果就是真或者假,也就是1、0。
<=、>=是雙目運算子,而且兩者優先順序相同,所以從左邊開始結合,即先判斷1<=a
為真,也就是為1,接下來判斷1<=10
也自然為真,輸出in range。
判斷下列程式的輸出:
void
swap
(int c,
int d )
intmain
(void
)
輸出:2,3
這裡涉及到形參與實參的區別,形參與實參的區別如下:
1.形參只在函式被呼叫的時候才會分配記憶體,呼叫結束後,一般情況釋放記憶體,所以形參只在函式內部有效。
2.形參和實參必須在數量、位置、型別上一致。
3.函式呼叫中資料的傳遞方向是單向的,只能把實參的值傳給形參,也就是一旦完成引數的傳輸,形參和實參就再也沒有瓜葛了。
所以,對於這道題,swap( a, b )只是將a、b的值傳給形參,在swap函式中,交換的是形參,與a、b沒有關係,所以實際上a、b變數並沒有完成交換。
void
swap
(int
* c,
int* d )
intmain
(void
)
執行如下:
C 每日一題
題目 給定乙個陣列 nums 和乙個值 val 你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 o 1 額外空間的條件下完成,oj鏈結.解析 我們來解析一下這個題目的做題思路,他的含義就是讓我們刪除掉陣列中的元素,然後將陣...
每日一題 1
題目詳情 peter喜歡玩數字遊戲,但數獨這樣的遊戲對他來說太簡單了,於是他準備玩乙個難的遊戲。遊戲規則是在乙個n n的 裡填數,規則 對於每個輸入的n,從左上角開始,總是以對角線為起點,先橫著填,再豎著填。這裡給了一些樣例,請在樣例中找到規律並把這個n n的 列印出來吧。輸入描述 多組測試資料 資...
每日一題2018 3 21
leetcode 2 模擬十進位制運算考察單鏈表基本操作。題無難點,個人基礎需要提高。definition for singly linked list.struct listnode class solution while p while q if shi val s next null ret...