歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言指針的相關概念

C語言指針的相關概念

日期:2017/3/1 9:39:28   编辑:Linux編程

1、基礎概念

在 C語言裡,基本變量存放的是數據,而指針變量是存放地址的變量(另一變量額地址)。在 c 語言中,指針也稱之為地址,所以我們常說某某變量的指針,可以理解為某某變量的在內存中的地址。如:b 變量的指針是 1000,可以理解為 b 在內存中的地址是 1000,注意不能理解為 b 的指針變量是4004(錯誤的理解)。

2、定義指針變量

在 c 語言指針的定義形式如下:

類型說明符 *指針變量名

如:

int *p1,*p2;
 
//錯誤的定義方式
int* p1,p2;// p1 整形指針,p2 是整形變量

在 c 裡,可以在變量前加 & 符號取得變量的地址,同樣地,可以在指針變量前加 * 符號取得指針變量指向的變量的值(該內存地址上存放的數據),如:

int a = 4;
int *p = &a;
printf("指針 p 指向的變量的值是 %d \r\n",*p);// 注意在這行代碼裡, p 是指針, *p 是指向的變量的值

3、指針變量作為函數參數

//帶有指針變量的函數定義形式如下
void fun(int *p1,int *p2)

//調用方式如下:
int *ptr1 = &a1;
int  *ptr2 =  &a2;
fun(ptr1,ptr2)

注:在被調用函數中,試圖修改指針變量的值(即地址)來達到改變實參的目的都是錯誤的.

這句話如何理解呢?這裡牽涉到一個比較容易混淆的問題-值傳遞和引用傳遞的區別.在這裡提供一種理解方式,如下:將實參傳給形參的時候,形參都是將實參的內容復制一遍,再調用相對應的函數.

void swap1(int num1,int num2){
	int temp = num1;
	num1 = num2;
	num2 = temp;
}
void swap2(int *num1,int *num2){
	// 試圖修改指針變量的值(地址)
	int *temp = num1;
	num1 = num2;
	num2 = temp;
}
void swap3(int *num1,int *num2){
	int temp = *num1;
	*num1 = *num2;
        *num2 = temp;
}

int main(){
	int a = 1,b = 2;
	int *ptr1 = &a,*ptr2 = &b;
	swap1(a,b);	// 結果不變:a = 1,b = 2

	swap2(ptr1,ptr2);	// 結果不變,a = 1,b = 2

	swap3(ptr1,ptr2); // a = 2, b =1
}
4、字符串與指針
    字符串是字符的集合,可以使用數組(指針常量)或指針變量來表示。
char *str1 = "tianya";
char str2[] = "tianya";
    在上面代碼中: str1 是一個指針變量,str2 是指針常量,所以 str2 不能使用 ++ 或 —— 運算符。輸入對應字符串的值如下:
printf("str1 的值為 %s \n",str1);
printf("str2 的值為 %s \n",str2);

另外,我們還需要理解一下,下面這幾個的定義方式的不同:

char *str = "tianya";
char str[] = "tianya";
char str[10] = "tianya";
char str[2] = "tianya";

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題
5、一維數組和指針 數組與指針,是一個比較容易讓人迷惑的地方,最主要就是各種不同的表示方式所代表的不同的含義,下面我們一步步來理解一下不同的方式: 1) 定義方式:
int a[5];    // a 其實是一個常量指針,指向數組的第一個元素 a[0]
int *p = a;    // 等效於:int *p = &a[0];

2) 通過指針引用數組元素

int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("the seconde elem is %d \n",a[1]);//20
printf("the seconde elem is %d \n",*(a+1));//20
printf("the seconde elem is %d \n",p[1]);//20
printf("the seconde elem is %d \n",*(p+1));//20

類似地推算,我們可以知道:a[i] 等同於 *(a+i),當中 a[0] 等同於 *a 或 *(a+0);*(p+i) 等同於 ptr[i]。看過一些書,會有著這樣一種介紹 * 和 [] 等同,,結合前面的例子,我們再看另外一個例子:

int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("the seconde elem is %d \n",a[1]+1);//21
printf("the seconde elem is %d \n",*a+1);//11,可以看成 (*a)+1 或 *(a+0)+1
printf("the seconde elem is %d \n",p[1]+1);//21
printf("the seconde elem is %d \n",*p+1);//11,可以看成 (*p)+1 或 *(p+0)+1

是不是覺得我們基本可以了解這些使用了,我們再深入地學習一下,當 * 與 ++ 或 —— 相遇時,又會是一種什麼樣的情況:

// 第一種情況
int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("*p++ = %d \n",*p++);	// 10,可以看成是 *(p++)

// 第二種情況:
int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("*++p = %d \n",*++p);	//20,可以看成 *(++p)

// 第三種情況
int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("++*p = %d \n",++*p);	// 11,可以看成 ++(*p)

* 與 ++ 或 -- 的運算符優先級相同,結合性是由右往左。如果覺得基本都懂的,那猜猜一下下面這個例子會輸出什麼?

int a[5] = {10,20,30,40,50};
int *p = a;    // 或 int *p = &a[0];
printf("*p++ = %d \n",*p++);	
printf("*++p = %d \n",*++p);
printf("++*p = %d \n",++*p);

現在的我們可以來總結一下:

當 p = &a[i] 時,則有:

  • *p++ 相當於 a[i++];
  • *++p 相當於 a[++i];
  • *p-- 相當於 a[i--];
  • *—p 相當於 a[—i];

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-09/107009p2.htm

Copyright © Linux教程網 All Rights Reserved