指標:指標本身也是乙個變數,它的內容是指向的內容的位址。指標同樣有型別的區分,char 的指標只能指向char型資料,int 指標指向int型資料。但是指標所佔記憶體單元的大小(即其內容)是跟作業系統的位址位數有關,比如32位位址的系統,那麼指標所佔的記憶體單元就是4個位元組,16位就是2個位元組,因此,指標的型別只是限定它所指向的變數的型別,其內容所佔的單元大小是與作業系統的位址位數相關,與變數型別無關。
在32位位址系統中,比如:
int a = 10; //int型一般長度為4位元組,所以sizeof(a)的值為4
int * p =a; // p中存放的是a的位址,所以sizeof(p)的長度是4位元組
char b = 'c'; // char型一般長度為1個位元組,所以sizeof(b)值為1
char * d = c; // d中存放的依然是a的位址,所以sizeof(d)值為
// 4(而不是 1 !)
注意:void * 指標是未確定的指標,它可以指向任何型別的變數。
陣列:陣列是乙個連續占有一段記憶體單元的變數集合。
比如:
int a[10];// a:陣列名,代表的是當前陣列所在的首位址。
a = 3; // 錯誤;陣列名a不是乙個變數,它是乙個位址常量,因
// 此對於a的賦值或自增是會報錯的;
指標與陣列區別:
1、指標是乙個單獨變數,只是指向了其他變數的位址(相當於彙編中的間接定址,與位址暫存器類似);
陣列是一串元素序列並且真實的儲存元素內容,它的陣列名可以相當乙個指標(與指標的用法「基本」一樣),代表陣列的首位址;
比如:
int a[10]; //系統實實在在分配了10*4個位元組的連續記憶體單元
int* p=a; //也可以寫成 int* p = &a[0];p指向陣列a[10]的首位址a[0];
//p只是乙個變數,只佔據4個記憶體單元,儲存的是陣列a的首位址
其實:p=p[0]=a[0]=*a;(p+i)=p[i]=a[i]=*(a+i);指標和數
組的取值可以互換。
2、 sizeof對於指標變數和陣列的處理是不一樣的。拿上面的指標p 和陣列a[10]來說,對於乙個32位位址的系統。
sizeof(p)的值為 4 個位元組;
sizeof(a)的值為 40 個位元組;
原因是因為,p是乙個指標變數其內容儲存的是4個位元組的位址;而陣列名a並不是乙個變數,它是乙個常量的位址,sizeof將其視為整個陣列的代表,因此計算的時候會計算整個陣列的大小。
但是下面的情況又會不同:
void computesize(int
*a,int b, int c[10]);
int main()
void computesize(int
*a,int b,int c[10])
這時執行strlen(a,a,a); 假設是32位位址系統。
輸出的值並不是4、40、40,而是4、4、4,那是不是有矛盾了呢?並不是的,因為這牽扯到了另乙個知識點——函式引數的傳遞。我們知道,傳遞引數有值傳遞和位址傳遞。上面的情況就屬於位址傳遞,無論形參是*a、b還是c[10],傳入的時候都是將首位址傳給指標變數a 、b、c。b與c的不同就是b沒有指定長度,而c指定了長度。這時候其實a、b、c相當於乙個指標變數而不是之前的陣列了,否則每一次傳遞都要重新弄乙個副本,系統會吃不消的。
int main()
void fun(int *a,int b);
傳進去的都是乙個位址變數,sizeof計算出來的大小是一樣的(但是在定義他們的地方sizeof的長度是不一樣的)。
2、字元指標與函式:
//定義乙個陣列,記憶體中只有陣列,存放在堆疊中(注意,此時字串不是
//常量字串,不在靜態區而是在陣列所在的堆疊記憶體中)。
char ameg = "i am a boy.";
//定義乙個指標變數,記憶體中具有乙個指標變數和乙個字串常量,並且字
//符串常量存放在靜態區中,指標在堆疊中分配。
char * pmeg = "i am a boy.";
1、指標陣列:
形如:int * p[10]; //乙個指標陣列,陣列裡面有10個元素,每乙個元素都是乙個int型的指標
陣列內的每乙個元素都是乙個指標變數(這時注意每個元素所佔的記憶體單元大小是位址的長度而不是型別長度)
2、陣列指標:
*(b) = b[0][0]; *(b+1) = b[1][0]; *(*(b+i)+j) = b[i][j]
3、指向指標的指標:形如: int **c = p;//二級指標c,指向了指標陣列p的首位址&p[0],即指向了指標陣列的第乙個指標的位址
該指標大小也是取決於作業系統,它跟一級指標其實本質上是沒有差別的,只是說是有連環指向的這種感覺。
c是指向指標的指標,因此它使用間接取址符時需要兩次才能取出目標的內容。
比如:*c表示的是p[0]的位址,而**c表示的是p[0]位址中的內容
c == &p[0]; // 指標陣列中第乙個指標元素的位址
*c == p[0]; // 指標陣列中第乙個指標元素位址的內容,即目標變數的位址
**c == *p[0]; // 指標陣列中第乙個指標元素指向的目標變數值
1、*與++運算子的優先順序相同,而且都是右結合的(一元都是的)。
a = *p++ :表示先將指標p自增,然後再取指標的內容賦值給a;
a =(*p)++: 表示先取指標內容賦值給a,然後指標再自增
2、/、*、%等二元運算子具有相同的優先順序,而且結合性是自左向右的。
a = 1/2*a: 因為是自左向右結合的,故表示的是 0.5*a,然後再賦值給a。
a = 1/(2*a): 這才表示求2*a的倒數,然後賦值給a。
3、字串陣列和指標
當指標指向字串常量時,通過指標是不能修改字串常量的值的。如:
char * p1 = "hello world";
p1[5] = ','; //錯誤,這是一種c語言標準未定義的操作
對於p1[5] = 『,』;不同系統會給出不同結果,在turbo c環境下,可能會完成賦值過程,但是對於像vc++、dev-c++來說這是乙個錯誤的操作,因為「hello world」是乙個字串常量,儲存在常量區,從c語言的概念和定義上講,是沒有這個標準的。
4、利用malloc分配記憶體
如果想將某乙個字串複製到某乙個控制項,一定要記得分配足夠的空間大小,不要忘記」\0」結束符。 比如:
char * strsrc = "hello boy.";
char * strdest;
//錯誤,strlen並未計算"\0"結束符,賦值後的指標末尾指向未知空間。
strdest = (char *) malloc(strlen(strsrc));
//正確,為"\0"留出空間。
strdest = (char *) malloc(strlen(strsrc)+1);
strcpy(strdest,strsrc);
5、空指標和空字串的差別
空指標是指向0(null)的指標,c語言保證對空指標的操作是安全的。如下:
char * p = null; // #define null 0 ,這是c語言定義的null
而空字串則是乙個只有乙個』\0』結束符的字串,它在記憶體中是有儲存空間的。比如:
char p ="";
char p1 = "\0";//與上面不同,這裡佔據兩個字元空間
char a[10];
printf("%d , %d \n",sizeof(p),strlen(p)); //輸出為1,0 說明占有乙個位元組空間,注意此時strlen(p)為0,
printf("%d , %d \n",sizeof(p1),strlen(p1)); //輸出為2,0 說明占有兩個位元組空間,注意此時strlen(p1)為0!
6、strlen與sizeof的區別
7、使用未初始化的指標
int
x,*p;
x=10;
*p = x; // 錯誤,p並未指向乙個確定的地方,它並沒有被初始化。
8、null指標
null指標並不指向任何物件,在賦值和比較運算意外的其他運算子都是非法的。由於標準並未對null指標賦值運算、比較運算意外的運算進行定義,因此這些運算都將得到乙個不確定的結果。有時候可能給系統帶來災難性的後果。 如:
int
*p = null;
intx = 10;
int a = *p * x;
int b = *p * x;
printf("%d
%d",a,b); //在 dev 上執行出錯
C 易混淆知識點
c 易混淆知識點 crystal 例項 static void main string args 執行結果為 有了上面的理論基礎,下面就具體分析上面程式為什麼會是那樣的結果 首先m1,m2都是引用型別,當執行m1 m2操作時,比較的是m1與m2在棧內位址的值是否相等,即比較的是引用,因為m1和m2指...
java語言易混淆知識點
s.substring a,b a,b含義 不可變字串string 修改 先提取字串再拼接 和equals區別 空串和null串 空串是長度為0內容為空 null串表示目前沒有任何與該變數的關聯 檢查乙個字串是否為null if str null 檢查乙個字串既不是null也不是空串 if str ...
PMP 易混淆知識點
敏感性分析有助於確定哪些風險對專案具有最大的潛在影響。它有助於理解專案目標的變化與各種不確定因素的變化之間存在怎樣的關聯。把所有其他不確定因素固定在基準值,考察每個因素的變化會對目標產生多大程度的影響。敏感性分析的典型表現形式是龍捲風圖。基於單項任務的成本和進度的概率分布,模擬出成百上千種可能結果的...