欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言指針必備基礎全面覆蓋

 更新時間:2021年10月25日 16:42:59   作者:波風張三  
數(shù)據(jù)對象是指存儲在內(nèi)存中的一個指定數(shù)據(jù)類型的數(shù)值或字符串,它們都有一個自己的地址,指針是保存這個地址的變量,本篇文章帶你掌握C語言指針的用法

前言

指針是C語言中的一個重要概念。正確而靈活的運用指針,可以使程序間接、緊湊、高效。每一個學習和使用C語言的人,都應當深入地學習和掌握指針。

提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、指針是什么?

指針是包含內(nèi)存地址的變量,這個地址是內(nèi)存中另一個對象(通常是另一個變量)的位置。例如如果一個變量包含另一個變量的地址,我們說第一個變量指向第二個變量。

相信大家看到上面這段話,可能有點懵,不急,我稍后再給大家解釋。在這里,我先給大家講述一下,數(shù)據(jù)在內(nèi)存中是如何存儲和讀取的?

1.數(shù)據(jù)在內(nèi)存中的存儲

如果在程序中定義了一個變量,在對程序進行編譯的時候,系統(tǒng)就會給這個變量分配內(nèi)存單元。編譯系統(tǒng)根據(jù)程序中的定義的變量類型,分配一定長度的空間

在這里插入圖片描述

那么,這些字節(jié)在內(nèi)存中被分配到哪里?我們?nèi)绾握业侥兀?br /> 為了解決這個問題,我們就給內(nèi)存區(qū)的每一個字節(jié)一個編號,這個就是它們的“地址”。它相當于旅館中的房間號,在地址所標志的內(nèi)存單元中存放的數(shù)據(jù)則相當于旅館房間中居住的旅客。

在這里插入圖片描述

所以指針是個變量,存放內(nèi)存單元的地址(編號)

2.一個小的單元到底是多大?

1、對于32位的機器,假設有32根地址線,那么假設每根地址線在尋址的時候產(chǎn)生高電平(高電壓)和低電平(低電壓)就是(1或者0);

2根地址線上的電信號轉(zhuǎn)換成數(shù)字信號用(1/0)表示,所以可能性
00000000000000000000000000000000–11111111111111111111111111111111
也就是有2^32 編號,說明可以管理2的32次方個單元
這里就有2的32次方個地址。

每個地址標識一個字節(jié),那我們就可以給
(2^32Byte == 2^32/1024KB == 2^32 /1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空閑進行編址。

按照同樣的方法,我們可以計算出64四位機器,下面就直接給結(jié)論了。

1、在32位的機器上,地址是32個0或者1組成二進制序列,那地址就得用4個字節(jié)的空間來存儲,所 以一個指針變量的大小就應該是4個字節(jié)。
2、在64位機器上,如果有64個地址線,那一個指針變量的大小是8個字節(jié),才能存放一個地址

指針的大小在32位平臺是4個字節(jié),在64位平臺是8個字節(jié)。

二、指針變量

1.什么是指針變量

思考一個問題,在編譯器中,如何把3賦值給i這個變量中?

第一種作法,把3直接送到i所表示的單元中,例如“i=3”;

int main()
{
	int i=3;
	return 0;
}

第二種方法,把3送到變量p所指向的單元(即變量i的存儲單元,也就是地址,如p=3,其中i表示p指向的對象)

int main()
{
	int i;
	//int i = 3;//第一種方法
	int *p = &i;//第二種方法
	//這里我們對變量a,取出它的地址,可以使用&操作符。
   //將i的地址存放在p變量中,p就是一個指針變量。
	*p = 3;
	printf("%d\n", i);
	return 0;
}

在這里插入圖片描述

2.指針類型

思考一個問題:

把int型變量a和float型變量b先后分配到2000開始的存儲單元中,&a和&b的信息完全相同嗎?

答案是不相同的,因為雖然存儲單元的編號相同,但他們的數(shù)據(jù)類型不同。

此外,還因為數(shù)據(jù)類型的不同,無法確定是從一個字節(jié)中取信息(字符數(shù)據(jù)),還是從兩個字節(jié)取信息(短整型),抑或是從四個字節(jié)取信息(整型),不同的類型,存儲方式是不一樣的。

如果我們要將&num(num的地址)保存到p中,我們需要我們給指針變量相應的類型。

如下:

char  *pc = NULL;//har* 類型的指針是為了存放 char 類型變量的地址。
int   *pi = NULL;//int* 類型的指針是為了存放 int 類型變量的地址。
short *ps = NULL;//short* 類型的指針是為了存放 short 類型變量的地址
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

這里可以看到,指針的定義方式是: 類型名 * 指針變量名 。

【總結(jié)】

C語言中的地址包括位置信息(內(nèi)存編號,或稱純地址)和它所指向的數(shù)據(jù)的類型信息,或者說它是“帶類型的地址”,如&a,一般稱它位“變量a的地址”,但是確切地說,它是“整型變量a的地址”

3.指針類型的作用

作用一:

指針類型決定了指針解引用操作的時候,一次訪問幾個字節(jié)(訪問內(nèi)存的大?。?/p>

int main()

{	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;
	return 0;
}

在這里插入圖片描述

int main()
{
	int a = 0x11223344;
/*	int* pa = &a;
	*pa = 0;*/
	char* pc = &a;//int*
	*pc = 0;
	return 0;
}

在這里插入圖片描述

指針類型的意義1

指針類型決定了指針解引用操作的時候,一次訪問幾個字節(jié)(訪問內(nèi)存的大?。?
char* 指針解引用訪問1個字節(jié)
int* 指針解引用訪問4個字節(jié)

作用二:

指針類型決定了,指針±整數(shù)的時候的步長(指針±整數(shù)的時候,跳過幾個字節(jié))

int main()
{
	int a = 10;
	int * pa=&a;
	char *pc = &a;
	printf("%p\n", pa);
	printf("%p\n", pc);

	printf("%p\n", pa+1);//如果是整型指針int*,+1則跳過4個字節(jié)、
	printf("%p\n", pc+1);//char* 指針+1,跳過1個字節(jié)
	return 0;
}

在這里插入圖片描述

三、野指針

1.什么是野指針

概念: 野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)

什么意思?舉個例子
就是你撿到一把鑰匙,但是不知道它可以開那道門。

2.野指針成因

2.1. 指針未初始化

指針沒有初始化,里面放的是隨機值

#include <stdio.h>
int main()
{ 
 	int *p;//局部變量指針未初始化,默認為隨機值
    *p = 20;//通過p中存的隨機值作為地址,找到一個空間,這個空間不屬于我們當前的程序,就造成了非法訪問
//如果非法訪問了,p就是野指針
 return 0; }

2.2指針越界訪問

指針越界造成野指針問題

int main()
{
	int arr[10] = 0;
	int i = 0;
	int * p = arr;

	for (i = 0; i <= 10; i++)//這里循環(huán)了11次,當指針指向的范圍超出數(shù)組arr的范圍時,p就是野指針
	{
		*p = 1;
		p++;
	}
	return 0;
}

2.3指針指向的空間釋放

當一個指針指向的空間釋放了,這個指針就變成野指針了

int* test()
{
	int a = 10;
	return &a;  //int *,生命周期,出來就銷毀了
}
int main()
{
	int *p = test();
	//printf("不愧是你\n");//加入這里加了一條語句,下面的值就變了
	printf("%d\n", *p);//編譯出10是因為編譯器會對值做一次保留。所以能訪問到上面函數(shù)不一定是對的
	return 0;
}

3.如何規(guī)避野指針

  • 指針初始化
  • 小心指針越界
  • 指針指向空間釋放即使置NULL
  • 避免返回局部變量的地址
  • 指針使用之前檢查有效性
//規(guī)避野指針
int main()
{
	int a = 10;
	int * p = &a;//1、明確初始化,確定指向

	int * p2 = NULL;//NULL本質(zhì)是0,2、不知道一個指針當前應該指向哪里是,可以初始化位NULL
	//*p2 = 100;//err,對于空指針,是不能直接解引用的

	//如何規(guī)避? 
	if (p2 != NULL)//先判斷是不是空指針
	{
		*p2 = 100;//這樣才對
	}

}

四、指針運算

1.指針±整數(shù)

int main()
{
	float arr[5];
	float *p;
	for (p = &arr[0]; p < &arr[5];)
	{
		*p++ = 0;//對一個指針加1使它指向數(shù)組中的下一個元素,把指針指向的內(nèi)容全部賦值給0
	}
	return 0;
}

在這里插入圖片描述

也就說,如果加2使它向右移動2個元素的位置,依次類推。把一個指針減去2使它向左移動2個元素的位置。

2.指針-指針

1、指針減去指針的前提,是兩個指針指向同一塊區(qū)域
2、指針減去指針,得到數(shù)字的絕對值,是指針和指針之間元素的個數(shù)

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	char ch[5] = { 0 };
	//printf("%d\n", &arr[9] - &ch[0]);//這種算法是錯誤的

	printf("%d\n", &arr[9] - &arr[0]);//算出的是元素的個數(shù)
	printf("%d\n", &arr[0] - &arr[9]);//
	//指針減去指針的前提,是兩個指針指向同一塊區(qū)域
	//指針減去指針,得到數(shù)字的絕對值,是指針和指針之間元素的個數(shù)

	return 0;
}

在這里插入圖片描述

【注意】
指針與指針之間不能進行加法運算,因為進行加法后,得到的結(jié)果指向一個不知所向的地方,沒有實際意義

什么意思,舉個例子。

在這里插入圖片描述

五、指針和數(shù)組

1.數(shù)組元素的指針

一個變量有地址,一個數(shù)組包含若干元素,每個數(shù)組元素都在內(nèi)存中占用存儲單元,它們都有相應的地址。

指針變量既然可以指向變量,當然也可以指向數(shù)組元素,也就是把某一元素地址放到一個指針變量中。

所謂數(shù)組元素的指針就是數(shù)組元素的地址

(1)用一個指針變量指向一個數(shù)組元素

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	int* p;//定義p位指向整型變量的指針變量
	p = &arr[0];//把a[0]元素的地址賦給指針變量p
	return 0;
}

以上是使指針變量p指向a數(shù)組的第0號元素

在這里插入圖片描述

2.通過指針引用數(shù)組元素

(1)下標法,如a[i]形式
(2)指針法,如*(a+i)

下標法:

int main()
{
	int arr[10];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
	printf("%p\n", arr);//數(shù)組名就是首元素地址
	//下標法
	printf("%p\n", &arr[0]);
	int* p=&arr[5];//整型地址放在整型指針上,從而讓指針跟數(shù)組建立聯(lián)系

	//數(shù)組名確實是首元素地址,
	//但是有兩個例外
	//1.sizeof(數(shù)組名),這里的數(shù)組名不是首元素地址,是表示整個數(shù)組,計算的是整個數(shù)組的大小,單位是字節(jié)
	//2.&數(shù)組名,拿到的是整個數(shù)組的地址

	return 0; 
}

在這里插入圖片描述

指針法:

int main()
{
	int arr[10];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	int* p=&arr[0];//整型地址放在整型指針上,從而讓指針跟數(shù)組建立聯(lián)系
	//指針法
	for (i = 0; i < sz; i++)
	{
		*(p + i) = i;// p+i 其實計算的是數(shù)組 arr 下標為i的地址。
	}
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0; 
}

在這里插入圖片描述

一個小知識:

int main()
{

	int arr[10] = { 0 };
	arr;//數(shù)組名
	&arr[0];//取出首元素地址
	&arr;//取出整個數(shù)組的地址
	printf("%d\n", &arr[0]);
	printf("%d\n", &arr);
	return 0;
}

在這里插入圖片描述

六、二級指針

指針變量的地址二級指針

什么意思?舉個例子

int main()
{
	int a = 10;//4byte,向內(nèi)存申請4個字節(jié)
	int* p=&a;//p指向a,稱為一級指針

	int* *pp=&p;//pp就是二級指針,pp存放的是一級指針的地址
	* *pp = 20;//需兩層解引用	
	printf("%d\n", a);
	//int** * ppp = &pp;//ppp就是三級指針
	return 0;
}

七、指針數(shù)組

存放指針的數(shù)組就是指針數(shù)組

int main()
{
	int arr[10];//整型數(shù)組,存放整型的數(shù)組就是整型數(shù)組
	char ch[5];//字符數(shù)組,存放字符的數(shù)組就是字符數(shù)組
	//指針數(shù)組,存放指針的數(shù)組就是指針數(shù)組
	//int*  整型指針的數(shù)組
	//char* 字符指針的數(shù)組

	int* parr[5];//整型指針的數(shù)組,存放的類型都是int*
	char* pc[6];//字符指針的數(shù)組
	return 0;
}

我們也可以用同樣的方式來訪問指針數(shù)組。
如下

int main()
{
	int a = 10;
	int b = 20;
	int c = 30;

	int * arr[3] = { &a, &b, &c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d\n",*(arr[i]));
	}

	int *pa = &a;
	int *pb = &b;
	int *pc = &c;
	return 0;
}

在這里插入圖片描述

最后

本文介紹的是指針的基礎知識,往后還會繼續(xù)深入講解指針更深入的知識。此外,本文參考了譚浩強《C語言設計》(第五版),以及網(wǎng)上的部分資料,加之自己在學習聽課時的筆記,梳理而成,花費了我很多心思。當文章寫成之時,時間已過去4個多小時!

希望能對看到的大家有所幫助!

以上就是C語言指針必備基礎全面覆蓋的詳細內(nèi)容,更多關(guān)于C語言 指針的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言 module_init函數(shù)與initcall案例詳解

    C語言 module_init函數(shù)與initcall案例詳解

    這篇文章主要介紹了C語言 module_init函數(shù)與initcall案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語言函數(shù)棧幀解析

    C語言函數(shù)棧幀解析

    下面小編就為大家?guī)硪黄獪\談C語言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-09-09
  • C++基礎知識實例解析(一)

    C++基礎知識實例解析(一)

    這篇文章主要對C++基礎知識實例解析,通過四個簡短的案例,鞏固大家的基礎知識,需要的朋友可以參考下
    2015-08-08
  • OLEDB打開Excel文件的實現(xiàn)方法

    OLEDB打開Excel文件的實現(xiàn)方法

    下面小編就為大家?guī)硪黄狾LEDB打開Excel文件的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Qt數(shù)據(jù)庫應用之通用數(shù)據(jù)庫同步

    Qt數(shù)據(jù)庫應用之通用數(shù)據(jù)庫同步

    數(shù)據(jù)庫同步的主要功能是將本地的數(shù)據(jù)庫記錄同步到遠程的數(shù)據(jù)庫。本文將利用Qt實現(xiàn)通用數(shù)據(jù)庫同步功能,感興趣的小伙伴可以跟隨小編一起學習一下
    2022-03-03
  • C++作用域與函數(shù)重載的實現(xiàn)

    C++作用域與函數(shù)重載的實現(xiàn)

    本文主要介紹了C++作用域與函數(shù)重載的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • 深入淺出理解C語言初識結(jié)構(gòu)體

    深入淺出理解C語言初識結(jié)構(gòu)體

    C?數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,結(jié)構(gòu)是?C?編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項,本篇讓我們來了解C?的結(jié)構(gòu)體
    2022-02-02
  • Qt音視頻開發(fā)之利用ffmpeg實現(xiàn)解碼本地攝像頭

    Qt音視頻開發(fā)之利用ffmpeg實現(xiàn)解碼本地攝像頭

    一開始用ffmpeg做的是視頻流的解析,后面增加了本地視頻文件的支持,到后面發(fā)現(xiàn)ffmpeg也是支持本地攝像頭設備的,所以本文就來用ffmpeg實現(xiàn)解碼本地攝像頭功能吧
    2023-03-03
  • C語言時間函數(shù)之mktime和difftime詳解

    C語言時間函數(shù)之mktime和difftime詳解

    這篇文章主要為大家詳細介紹了C語言時間函數(shù)之mktime和difftime,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一,希望能夠給你帶來幫助
    2022-02-02
  • C++將字符串格式化的幾種方式總結(jié)

    C++將字符串格式化的幾種方式總結(jié)

    這篇文章主要介紹了C++將字符串格式化的幾種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評論