C語言復習筆記--指針(1)

? ? ? ? 今天我們進入指針的復習了.這部分有很多知識,話不多說,讓我們進入指針的世界吧.

內存和地址

? ? ? ? 要想學指針就不能不學內存和地址.

??內存

????????其中,每個內存單元,相當于?個學?宿舍,? 個字節空間??能放8個?特位,就好?同學們 住的??間,每個?是?個?特位。 每個內存單元也都有?個編號(這個編號就相當于宿舍房間的?牌號),有了這個內存單元的編號,CPU就可以快速找到?個內存空間.在計算機中我們把內存單元的編號也稱為地址。C語?中給地址起 了新的名字叫:指針.

????????所以我們可以理解為: 內存單元的編號 == 地址 == 指針

? ?究竟該如何理解編址

指針變量和地址

? 取地址操作符(&)

? ? ? ??在C語?中創建變量其實就是向內存申請空間,下圖為例子:

????????我們如何能得到a的地址呢?這里就要用到取地址操作符了.(打印地址需要用%p)例子為下面代碼:

#include<stdio.h>int main()
{int a = 10;printf("%p", &a);return 0;
}

? ? ? ? 注:&a取出的是a所占4個字節中地址較?的字節的地址。雖然整型變量占?4個字節,我們只要知道了第?個字節地址,就可以順藤摸?訪問到4個字節的數據.

??指針變量和解引用操作符(*)

????????指針變量

? ? ? ? 我們通過取地址操作符取到地址,我們需要把這個地址存到指針變量中.指針變量也是?種變量,這種變量就是?來存放地址的,存放在指針變量中的值都會理解為地址.

int main()
{int a = 10;int* p = &a;printf("%p\n", p);return 0;
}

????????如何拆解指針類型

????????我們看到p的類型是 int* ,我們該如何理解指針的類型呢?

????????這?p左邊寫的是 int* , * 是在說明pa是指針變量,?前?的 int 是在說明pa指向的是整型(int) 類型的對象.同樣的char的地址就會放入char*的指針變量中.

????????解引用操作符?

? ? ? ? 我們拿到地址是為了使用,我們只要拿到了地址(指針),就可以通過地址(指針)找到地址(指針) 指向的對象,這?需要的就是解引?操作符(*)?.

int main()
{int a = 10;int* p = &a;printf("%p\n", p);printf("%d", a);*p = 0;printf("%d", a);return 0;
}

? ? ? ? 在上面的代碼中,*p的意思就是通過pa中存放的地址,找到指向的空間, *p其實就是a變量了;所以*p?= 0,這個操作符是把a改成了0.

??指針變量的大小

? ? ? ?根據前面的內容,32位機器假設有32根地址總線,每根地址線出來的電信號轉換成數字信號后 是1或者0,那我們把32根地址線產?的2進制序列當做?個地址,那么?個地址就是32個bit位,需要4 個字節才能存儲。 如果指針變量是?來存放地址的,那么指針變的??就得是4個字節的空間才可以。 同理64位機器,有64根地址線,?個地址就是64個?進制位組成的?進制序列,存儲起來就需要 8個字節的空間,指針變的大小就是8個字節.

//sizeof的返回值是size_t,打印最好用%zd來打印
int main()
{printf("%zd\n", sizeof(char*));printf("%zd\n", sizeof(short*));printf("%zd\n", sizeof(int*));printf("%zd\n", sizeof(double*));return 0;
}

? ? ? ? 輸出結果:?

????????結論:

????????32位平臺下地址是32個bit位,指針變量大小是4個字節

????????64位平臺下地址是64個bit位,指針變量大小是8個字節

????????注意:指針變量的大小和類型是無關的,只要指針類型的變量,在相同的平臺下,大小都是相同的.

指針變量類型的意義

? ? ? ? 既然所有指針的大小在同一平臺下都是一樣的,那么為什么要各種各樣的指針類型呢?

??指針的解引用

? ? ? ? 看下面兩端代碼,并且在執行時用調試來看他們的內存空間的變化.

????????調試我們可以看到,代碼1會將n的4個字節全部改為0,但是代碼2只是將n的第1個字節改為0.

????????結論:指針的類型決定了,對指針解引?的時候有多?的權限(?次能操作?個字節).(char* 的指針解引?就只能訪問?個字節,? int* 的指針的解引?就能訪問四個字節).

??指針+-整數

? ? ? ? 先看一下下面的代碼:

int main()
{int a = 10;int* p1 = &a;char* p2 = &a;printf("%p %p\n", p1, p2);p1 += 1;    //p1加整數p2 += 1;    //p2加整數printf("%p %p\n", p1, p2);return 0;
}

? ? ? ? 結果如下,可以看到int*的指針加1向后走了4個字節,而char*只走了1個字節.?

????????結論:指針的類型決定了指針向前或者向后??步有多?(距離).

??void* 指針

????????在指針類型中有?種特殊的類型是 void* 類型的,可以理解為?具體類型的指針(或者叫泛型指針),這種類型的指針可以?來接受任意類型地址.但是 void* 類型的指針不能直接進?指針的+-整數和解引?的運算.

int main()
{int a = 10;char b = 'n';void* p1 = &a;void* p2 = &b;printf("%p %p", p1, p2);//err//*p1=0;//p2++;return 0;
}

?????????般 void* 類型的指針是使?在函數參數的部分?來接收不同類型數據的地址,這樣的設計可以 實現泛型編程的效果.在之后的復習中會了解到.

const修飾指針

??const修飾變量

????????變量是可以修改的,如果把變量的地址交給?個指針變量,通過指針變量的也可以修改這個變量。 但是如果我們希望?個變量加上?些限制,不能被修改,這就需要到const了.(例如下面的變量b.)

int main()
{//變量可以修改,指針也可以間接修改變量int a = 10;printf("%d\n", a);int* pa = &a;*pa = 0;printf("%d\n", a);//這里b是不可以修改的const int b = 10;//b = 0;        //err//如果像下面的話,就意味著可以通過p2去改變b的值了,這是不合理的//int* pb1 = &b;//*pb1 = 0;		這里不會報錯并且會改變b的值//所以這里一定要用const來修飾指針const int* pb2 = &b;//*pb2 = 0;		//errreturn 0;
}

??const修飾指針變量

? ? ? ? 在上面的代碼中我就用了const來修飾指針,下面讓我們來看下下面的代碼更加深入的學習.

void test1()
{int n = 10;int m = 20;int* p = &n;*p = 20;//ok?p = &m; //ok?
}
void test2()
{int n = 10;int m = 20;const int* p = &n;//*p = 20;		//ok?no const在*前修飾*p不可以通過指針改變指針指向的變量p = &m; //ok?
}
void test3()
{int n = 10;int m = 20;int* const p = &n;*p = 20; //ok?//p = &m;	   //ok?no const在*后修飾p不可以改變p的指向
}
void test4()
{int n = 10;int m = 20;int const* const p = &n;//*p = 20; //ok?no//p = &m; //ok?no//*前后都有const,既不能改變指向也不能通過指針改變指針所指變量
}
int main()
{test1();test2();test3();test4();return 0;
}

????????結論:const修飾指針變量的時候?

????????1.const如果放在*的左邊,修飾的是指針指向的內容,保證指針指向的內容不能通過指針來改變。 但是指針變量本?的內容可變.

???????? 2. const如果放在*的右邊,修飾的是指針變量本?,保證了指針變量的內容不能修改,但是指針指向的內容,可以通過指針改變.

指針運算

指針的基本運算有三種,分別是:? 1.指針+- 整數? ? ?2.指針-指針? ? ?3.指針的關系運算

??指針+- 整數

? ? ? ? 這個可以用來便利內存中連續存放的類型,例如數組.代碼見下:

int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };int* pa = &arr[0];for (int i = 0; i < 10; i++){printf("%d ", *(pa + i));}printf("\n");return 0;
}

??指針-指針

? ? ? ? 可以用來計算字符串的長度.下面是使用和注意事項:

int main()
{int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };char arr1[5] = { 'a','s','d','f','g' };int* p1 = &arr[0];int* p2 = &arr[5];char* p3 = &arr1[0];printf("%d\n", p2 - p1);//指針-指針,返回的是兩個指針之間的元素個數//printf("%d\n", p2 - p3);//err		//因為兩個指針類型不同,不知到返回哪一個并且兩個數組不是連續空間,無法判斷兩個數組中間相隔多少return 0;
}

??指針的關系運算

? ? ? ? 可以提供另一種便利數組的方法:

int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };int* pa = &arr[0];while (pa < (arr + 10))//指針的關系運算{printf("%d ", *pa);pa++;}printf("\n");return 0;
}

?野指針

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

? 野指針成因

????????1. 指針未初始化

????????2. 指針越界訪問(一般出現在數組的越界)

????????3. 指針指向的空間釋放(返回函數中局部變量的地址)

int* func()
{int a = 0;return &a;
}
int main()
{//err返回已經銷毀了的局部變量的地址//int* p = func();//可能有時候看不出錯誤,但是如果再調用函數破壞原來的函數棧幀,就會出現問題了return 0;
}

??如何規避野指針

? ? ? ? 1.指針初始化

????????如果明確知道指針指向哪?就直接賦值地址,如果不知道指針應該指向哪?,可以給指針賦值NULL. NULL 是C語?中定義的?個標識符常量,值是0,0也是地址,這個地址是?法使?的,讀寫該地址會報錯.

? ? ? ? 2.小心指針越界

????????3.指針變量不再使?時,及時置NULL,指針使?之前檢查有效性

檢查代碼大概為

if ( p != NULL )

{

????????//代碼

}

? ? ? ? 4.避免返回局部變量的地址

? ? ? ? 以上就是今天的復習啦,還有一個有用的斷言,我將新開一個小篇幅的博客簡單說一下~

C語言復習--assert斷言-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76365.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76365.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76365.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【藍橋杯每日一題】4.1

&#x1f3dd;?專欄&#xff1a; 【藍橋杯備篇】 &#x1f305;主頁&#xff1a; f狐o貍x "今日禿頭刷題&#xff0c;明日榮耀加冕&#xff01;" 今天我們來練習二分算法 不熟悉二分算法的朋友可以看&#xff1a;【C語言刷怪篇】二分法_編程解決算術問題-CSDN博客 …

【設計模式】過濾器模式

過濾器顧名思義&#xff0c;定義一些過濾規則&#xff0c;將符合要求的內容篩選&#xff0c;就比如過濾不同大小或者不同顏色的水果&#xff0c;需要顏色和大小過濾器&#xff0c;篩選條件獨立為對象&#xff0c;可以通過靈活組合形成過濾鏈條。避免大量使用判斷語句。 案例代…

STM32 CAN學習(一)

CAN總線應用最多的是汽車領域。 CAN&#xff08;Controller Area Network&#xff09;控制器 局域 網 局域網&#xff1a;把幾臺電腦連接到一臺路由器上&#xff0c;這幾臺電腦就可以進行通訊了。 控制器在汽車中的專業術語叫做ECU&#xff08;Electronic Control Unit&…

多線程開發中List的使用

由于ArrayList在多線程高并發情況下是不安全的&#xff0c;因此要慎用&#xff0c;那么此時如果涉及到集合操作&#xff0c;應該怎么選&#xff1a; 方案一&#xff1a;Vector: 特點&#xff1a;通過給所有方法都用 synchronized 修飾從而保證線程安全&#xff0c; 缺點&…

論文閱讀筆記:Denoising Diffusion Implicit Models (2)

0、快速訪問 論文閱讀筆記&#xff1a;Denoising Diffusion Implicit Models &#xff08;1&#xff09; 論文閱讀筆記&#xff1a;Denoising Diffusion Implicit Models &#xff08;2&#xff09; 論文閱讀筆記&#xff1a;Denoising Diffusion Implicit Models &#xff08…

人工智能在醫療領域的前沿應用與挑戰

在當今數字化時代&#xff0c;人工智能&#xff08;AI&#xff09;技術正以前所未有的速度改變著我們的生活&#xff0c;其中醫療領域無疑是受益最為顯著的行業之一。從疾病診斷、治療方案制定到患者護理&#xff0c;AI的應用不僅提高了醫療服務的效率和質量&#xff0c;還為醫…

【計算機網絡】HTTP與HTTPS

文章目錄 1. HTTP定義2. HTTP交互3. HTTP報文格式3.1 抓包工具-fiddler3.2 抓包操作3.3 報文格式3.3.1 請求報文3.3.2 響應報文 4. URL5. 請求頭中的方法6. GET和POST的區別7. HTTP報頭7.1 Host7.2 Content_Length7.3 Content_Type7.4 User-Agent(UA)7.5 Referer7.6 Cookie 8 狀…

怎樣提升大語言模型(LLM)回答準確率

怎樣提升大語言模型(LLM)回答準確率 目錄 怎樣提升大語言模型(LLM)回答準確率激勵與規范類知識關聯類情感與語境類逆向思維類:為什么不,反面案例群體智慧類明確指令類示例引導類思維引導類約束限制類反饋交互類:對話激勵與規范類 給予獎勵暗示:在提示詞中暗示模型如果回…

【分享】內外網文件擺渡系統:讓數據傳輸更安全更可靠

【分享】Ftrans內外網文件擺渡系統&#xff1a;讓數據傳輸更安全更可靠&#xff01; 隨著大數據時代的到來&#xff0c;數據的重要性日漸得到重視&#xff0c;數據作為數字經濟時代下的基礎性資源和戰略性資源&#xff0c;是決定國家經濟發展水平和競爭力的核心驅動力。以行業…

Python自動化面試通關秘籍

Python自動化測試工程師面試&#xff0c;不僅僅是考察你的代碼能力&#xff0c;更看重你如何在項目中靈活運用工具和框架解決實際問題。如果你正準備面試&#xff0c;這篇文章將為你總結最常見的高頻考題及答題技巧&#xff0c;幫助你快速上手&#xff0c;通關面試&#xff0c;…

Logstash開啟定時任務增量同步mysql數據到es的時區問題

本文使用修改時間modify_date作為增量同步檢測字段&#xff0c;可檢測新增和修改&#xff0c;檢測不到刪除&#xff0c;檢測刪除請使用canal查詢binlog日志同步數據 檢測修改時間字段為varchar的時候可以先創建索引&#xff0c;并設置對應的mapping為&#xff08;可以無視時區…

如何使用 FastAPI 構建 MCP 服務器

哎呀&#xff0c;各位算法界的小伙伴們&#xff01;今天咱們要聊聊一個超酷的話題——MCP 協議&#xff01;你可能已經聽說了&#xff0c;Anthropic 推出了這個新玩意兒&#xff0c;目的是讓 AI 代理和你的應用程序之間的對話變得更順暢、更清晰。不過別擔心&#xff0c;為你的…

【Git】-- 處理 Git 提交到錯誤分支的問題

如果你不小心把本應提交到 test 分支的代碼提交到了 master 分支&#xff08;但尚未 push&#xff09;&#xff0c;可以按照以下步驟解決&#xff1a; 方法一&#xff08;推薦&#xff09;&#xff1a;使用 git reset 和 git stash 首先&#xff0c;確保你在 master 分支&…

通用目標檢測技術選型分析報告--截止2025年4月

前言 本文撰寫了一份關于通用目標檢測&#xff08;General Object Detection&#xff09;的技術選型分析報告&#xff0c;覆蓋2000至2025年技術演進歷程&#xff0c;重點納入YOLO-World、RT-DETR、Grounding DINO等2024-2025年的最新模型。 報告將包括技術定義、行業現狀、技…

鏈路追蹤Skywalking

一、什么是Skywalking 分布式鏈路追蹤的一種方式&#xff1a;Spring Cloud SleuthZipKin&#xff0c;這種方案目前也是有很多企業在用&#xff0c;但是作為程序員要的追逐一些新奇的技術&#xff0c;Skywalking作為后起之秀也是值得大家去學習的。 Skywalking是一個優秀的國產…

websocket獲取客服端真實ip

在websocket建立連接時,獲取訪問客戶端的真實ip 1. websocket建立連接過程 2. pom依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>3. 添加配置,握…

NSSCTF(MISC)—[justCTF 2020]pdf

相應的做題地址&#xff1a;https://www.nssctf.cn/problem/920 binwalk分離 解壓文件2AE59A.zip mutool 得到一張圖片 B5F31內容 B5FFD內容 轉換成圖片 justCTF{BytesAreNotRealWakeUpSheeple}

部分國產服務器CPU及內存性能測試情況

近日對部分國產服務器進行了CPU和內存的性能測試&#xff0c; 服務器包括華錕振宇、新華三和中興三家&#xff0c;CPU包括鯤鵬、海光和Intel&#xff0c;初步測試結果如下&#xff1a; 服務器廠商四川華錕振宇新華三中興中興服務器HuaKun TG225 B1R4930 G5R5930 G2R5300 G4操作…

【無標題】Scala函數基礎

函數和方法的區別 1&#xff09; 核心概念 &#xff08;1&#xff09; 為完成某一功能的程序語句的集合&#xff0c;稱為函數。 &#xff08;2&#xff09; 類中的函數稱之方法。 2&#xff09; 案例實操 &#xff08;1&#xff09; Scala 語言可以在任何的語法結構中聲明…

uniapp -- 列表垂直方向拖拽drag組件

背景 需要在小程序中實現拖拽排序功能,所以就用到了m-drag拖拽組件,在開發的過程中,發現該組件在特殊的場景下會有些問題,并對其進行了拓展。 效果 組件代碼 <template><!-- 創建一個垂直滾動視圖,類名為m-drag --><scroll