C語言 【初始指針】【指針一】

引言

? ? ? ? 思緒很久,還是決定寫一寫指針,指針這塊內容很多,也不是那么容易說清楚,這里盡可能寫地詳細,讓大家理解指針。(未完序)

一、內存和地址

? ? ? ? 在講指針前,需要有一個對內存和地址的認識,不然后面的指針不是那么容易理解。在我們的內存中:一個字節里存儲著 0 或 1 的信息。那計算機是怎么快速找到對應的信息的呢?

? ? ? ? 回答:在內存中每個字節都有自己對應的地址,計算機通過找到地址,就能訪問地址里面的信息。

? ? ? ? 那么指針,就是一種可以存儲地址的數據類型。

二、一級指針

1.存地址:?

? ? ? ? ?重點:其實指針是很簡單的,只要會使用int ,float, double,long long 等數據類型,那么指針變量,你也一定會使用。

? ? ? ? ?先介紹一下指針變量是怎么創建的:

????????對應數據類型的后面加上*,就可以存儲該類型的內存地址

認識個東西 : & 取地址操作符,看下面的代碼:

	int b = 10;int* a = &b;

????????這段代碼創建了一個變量b,&b,就可以取出b的地址。
int* 就是int類型的指針變量,a 里面存的就是? b 的地址

通過調試來看一下:

?

可以看到 b 的地址?

下面通過監視窗口,看一下a里面存的是什么:

發現就是b的地址。

類似地,如果要存float數據類型的地址,就要創建float類型的指針變量:

	float c = 1.2;float* d = &c;

d中存儲的就是 c 的地址。

其他的數據類型一樣,包括自定義類型的數據。

可以自己多試試。

2.解讀地址對應的內容:?

要用到一個東西:解引用操作符:*

使用起來也特別簡單:

比如上面代碼中,a中存儲的是b的地址,*a,就可以找到b對應位置的內容了

來看代碼:?

#include<stdio.h>int main()
{int b = 10;int* a = &b;int c = *a;  //*a 等價于 bprintf("%d\n", c);*a = 20;   //改變a地址里面的內容,就是把b的內容給改了printf("%d\n", b);return 0;
}

運行結果:

????????是不是特別簡單,認為指針難,是因為你不理解每個符號的內容,這里給拆開來講,相信你一定明白了

3.指針變量的大小

int在內存中占4個字節,float在內存中占4個字節,double在內存中占8個字節,和int,float,double等類型一樣,指針類型在內存中也是占有字節的。

????????那指針類型在內存中占多少個字節呢?

先給出結論,下面來看代碼證明。

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

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

? 注意指針變量的大小和類型是無關的,只要指針類型的變量,在相同的平臺下,大小都是相同的。(和CPU里面的線路有一定的關系)

sizeof操作符同樣可以返回指針類型在內存中占多少個字節。?

#include<stdio.h>
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位平臺下:

運行結果:?

在64位平臺下:?

?運行結果:

?三、指針變量類型的意義

你是不是會有這么個疑問:

????????指針變量的大小和類型無關,只要是指針變量,在同一個平臺下,大小都是一樣的,為什么還要有各種各樣的指針類型呢?

其實指針類型是有特殊意義的,通過兩中方法來理解一下。

1.指針的解引用

下面看兩段代碼:?

//代碼1
#include <stdio.h>
int main()
{int n = 0x11223344;int* pi = &n;*pi = 0;return 0;
}
//代碼2
#include <stdio.h>
int main()
{int n = 0x11223344;char* pc = (char*)&n;*pc = 0;return 0;
}

代碼二中給int*類型,強制轉換成了char*類型。最后都解引用后賦值0

通過調試,來看一下兩段代碼在內存中的存儲。

代碼一:

代碼二:
????????相信聰明的你一定發現了不同,代碼1會將n的4個字節全部改為0,但是代碼2只是將n的第一個字節改為0。

得出結論:指針的類型決定了,對指針解引用的時候有多大的權限(一次能操作幾個字節)。 比如: char* 的指針解引用就只能訪問?個字節,而 int* 的指針的解引用就能訪問四個字節。?

?2.指針+ -整數

有了上面的結論,這個就很容易理解了

來看代碼:

#include <stdio.h>
int main()
{int n = 10;char* pc = (char*)&n;int* pi = &n;printf("%p\n", &n);printf("%p\n", pc);printf("%p\n", pc + 1);printf("%p\n", pi);printf("%p\n", pi + 1);return  0;
}

來看運行結果:?

????????char* 類型的指針變量+1跳過1個字節, int* 類型的指針變量+1跳過了4個字節。 這就是指針變量的類型差異帶來的變化。指針+1,其實跳過1個指針指向的元素。指針可以+1,也可以-1。?

結論:指針的類型決定了指針向前或者向后走一步有多大(距離)。

四、void* 指針?

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

?來看代碼:

#include <stdio.h>
int main()
{int a = 10;int* pa = &a;char* pc = &a;return 0;
}

這段代碼在編譯的時候肯定是會報警告的。(因為類型不兼容)

#include <stdio.h>
int main()
{int a = 10;void* pa = &a;void* pc = &a;//*pa = 10; 這樣寫是錯誤的//*pc = 0;return 0;
}

void* 類型的指針可以接收不同類型的地址,但是無法直接進行指針運算。

????????一般 void* 類型的指針是使用在函數參數的部分,用來接收不同類型數據的地址,這樣的設計可以實現泛型編程的效果。

五、指針運算?

1.指針+-整數

? ? ? ? 上面的一個代碼已經可以看出這個功能了,這里再通過一個案例來理解一下(也算是一個小的練習)

????????

通過地址來訪問一個數組。

#include<stdio.h>
int main()
{int arr[10] = { 1, 2, 3, 4, 5, 6, 7,  8, 9, 10 };int* p = &arr[0]; //取出首元素的地址int i = 0;int sz = sizeof(arr)/sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", *(p + i));}return 0;
}

運行結果:

?從這個案例中可以看出:*(p + i) 等價于 p[i]。(其實就是這樣)

這也可以說明數組名是就是數組首元素的地址。

不過有來個特例需要記一下:

1. &arr,對數組名取地址,得到的是整個數組的地址,而不是首元素的地址。

2. sizeof(arr),這里面的arr也是整個數組的地址,而不是首元素的地址。

把上面代碼改一下來證明一下:

#include<stdio.h>
int main()
{int arr[10] = { 1, 2, 3, 4, 5, 6, 7,  8, 9, 10 };int* p = &arr[0]; //取出首元素的地址int i = 0;int sz = sizeof(arr)/sizeof(arr[0]);for (int i = 0; i < sz; i++){//printf("%d ", *(p + i));printf("%d ", p[i]);}return 0;
}

只改了一個地方,就是輸出位置。

運行結果:

是不是又增加了新知識,嘿嘿(●ˇ?ˇ●)?

?2.指針-指針

? ? ? ? 后面位置的指針減前面位置的指針,可以計算出兩個指針之間字節個數。

來看參考代碼:

#include <stdio.h>
int my_strlen(char* s)
{char* p = s;while (*p != '\0')p++;return p - s;
}
int main()
{printf("%d\n", my_strlen("abc"));return 0;
}

運行結果:?

3.指針的關系運算

指針之間也是可以比較大小的

來看代碼:

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = &arr[0];int sz = sizeof(arr) / sizeof(arr[0]);while (p < arr + sz) //指針的???較{printf("%d ", *p);p++;}return 0;
}

運行結果:?

是不是又被震驚到了,哇嗚,竟然還可以這么寫。

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

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

相關文章

深入理解pthread多線程編程:從基礎到生產者-消費者模型

前言 在多核處理器普及的今天&#xff0c;多線程編程已成為提高程序性能的重要手段。POSIX線程&#xff08;pthread&#xff09;是Unix/Linux系統下廣泛使用的多線程API。本文將系統介紹pthread的關鍵概念&#xff0c;包括線程初始化、死鎖預防、遞歸鎖使用&#xff0c;并通過…

springboot 對接馬來西亞數據源API等多個國家的數據源

使用Spring Boot對接StockTV全球金融數據API指南 StockTV提供了覆蓋股票、外匯、期貨和加密貨幣的全球化金融數據接口。本文將通過Spring Boot實現對這些API的快速對接&#xff0c;并提供完整的代碼示例。 一、前期準備 1. 獲取API Key 訪問StockTV官網聯系客服獲取API Key…

軟件測試常用設計模式

設計模式的重要原則就是&#xff1a;高內聚、低耦合&#xff1b;通常程序結構中各模塊的內聚程度越高&#xff0c;模塊間的耦合程度就越低。 數據驅動測試&#xff1a;Data Driven Testing&#xff0c;簡稱DDT&#xff1b; 數據驅動指的是從數據文件&#xff08;如數據庫、Ex…

基于 Fluent-Bit 和 Fluentd 的分布式日志采集與處理方案

#作者&#xff1a;任少近 文章目錄 需求描述系統目標系統組件Fluent BitFluentdKafka 數據流與處理流程日志采集日志轉發到 Fluentd日志處理與轉發到 KafkaKafka 作為消息隊列 具體配置Fluent-Bit的CM配置Fluent-Bit的DS配置Fluentd的CM配置Fluentd的DS配置Kafka查詢結果 需求…

正則表達式(Regular Expression,簡稱 Regex)

一、5w2h&#xff08;七問法&#xff09;分析正則表達式 是的&#xff0c;5W2H 完全可以應用于研究 正則表達式&#xff08;Regular Expressions&#xff09;。通過回答 5W2H 的七個問題&#xff0c;我們可以全面理解正則表達式的定義、用途、使用方法、適用場景等&#xff0c…

爬蟲獲取1688關鍵字搜索接口的實戰指南

在當今電商行業競爭激烈的環境下&#xff0c;數據的重要性不言而喻。1688作為國內領先的B2B電商平臺&#xff0c;擁有海量的商品信息&#xff0c;這些數據對于商家的市場分析、選品決策、價格策略制定等都有著重要的價值。本文將詳細介紹如何通過爬蟲技術獲取1688關鍵字搜索接口…

如何快速解決django存儲session變量時出現的django.db.utils.DatabaseError錯誤

我們在學習django進行web編程的時候&#xff0c;有時需要將一些全局變量信息存儲在session中&#xff0c;但使用過程中&#xff0c;卻發現會引起數據庫的報錯。通過查看django源碼信息&#xff0c;發現其對session信息進行了ORM映射&#xff0c;如果數據庫中不存在對應的表信息…

C語言復習--assert斷言

assert.h 頭?件定義了宏 assert() &#xff0c;?于在運?時確保程序符合指定條件&#xff0c;如果不符合&#xff0c;就報錯終止運行。這個宏常常被稱為“斷?”。 assert(p ! NULL); 代碼在程序運?到這??語句時&#xff0c;驗證變量 p 是否等于 NULL 。如果確實不等于 NU…

STL新增內容

文章目錄 C11 中的 STL 新增內容容器算法 C14 中的 STL 新增內容容器算法 C17 中的 STL 新增內容容器算法 C20 中的 STL 新增內容容器算法 C11 中的 STL 新增內容 容器 std::array&#xff1a;這是一個固定大小的數組容器&#xff0c;和原生數組類似&#xff0c;但具備更好的…

C#測試Excel開源組件ExcelDataReader

使用微軟的com組件Microsoft.office.Interop.Excel讀寫Excel文件雖然可用&#xff0c;但是列多、行多的時候速度很慢&#xff0c;之前測試過Sylvan.Data.Excel包的用法&#xff0c;如果只是讀取Excel文件內容的話&#xff0c;還可以使用ExcelDataReader包&#xff0c;后者是C#開…

位置編碼匯總 # 持續更新

看了那么多還沒有講特別好的&#xff0c;GPT老師講的不錯關于三角函數編碼。 一、 手撕transformer常用三角位置編碼 GPT說&#xff1a;“低維度的編碼&#xff08;例如&#xff0c;第一個維度&#xff09;可以捕捉到大的位置差異&#xff0c;而高維度的編碼則可以捕捉到小的細…

Java 模塊系統深度解析

Java 模塊系統深度解析 Java 模塊系統&#xff08;Java Platform Module System, JPMS&#xff09;是 Java 9 引入的一項重要特性&#xff0c;它從根本上改變了 Java 應用程序的打包和依賴管理方式。本文將全面介紹 Java 模塊系統的核心概念、優勢及實際應用。 一、為什么需要…

藍橋杯杯賽-日期模擬

知識點 處理日期 1. 按天枚舉日期&#xff1a;逐天遍歷起始日期到結束日期范圍內的每個日期。 2. 處理閏年&#xff1a;正確判斷閏年條件。閏年定義為&#xff1a;年份 滿足以下任意一個條件&#xff1a;(閏年的2月只有29天) 滿足下面一個條件就是閏年 1> 是 400 的倍數…

.Net中對稱加密的實現

常見對稱加密算法及優缺點 1. DES&#xff08;Data Encryption Standard&#xff09; 優點&#xff1a;是最早被廣泛應用的加密算法&#xff0c;算法公開&#xff0c;實現簡單&#xff0c;效率較高。缺點&#xff1a;密鑰長度較短&#xff08;56 位&#xff09;&#xff0c;在…

SQLMesh調度系統深度解析:內置調度與Airflow集成實踐

本文系統解析SQLMesh的兩種核心調度方案&#xff1a;內置調度器與Apache Airflow集成。通過對比兩者的適用場景、架構設計和操作流程&#xff0c;為企業構建可靠的數據分析流水線提供技術參考。重點內容包括&#xff1a; 內置調度器的輕量級部署與性能優化策略Airflow集成的端到…

centos線程數查看

查看當前最大支持的線程數 cat /proc/sys/kernel/threads-max當前用戶進程可以創建的最大線程數&#xff08;包括子進程&#xff09; [rootlocalhost tmp]# ulimit -u得到當前實際的線程數 [rootlocalhost tmp]# ps -eLf | wc -l統計每個進程的總線程數前20的數據 [rootloc…

【大模型】視覺語言模型:Qwen2.5-VL的使用

官方github地址&#xff1a;https://github.com/QwenLM/Qwen2.5-VL 目錄 Qwen家族的最新成員&#xff1a;Qwen2.5-VL 主要增強功能 模型架構更新 快速開始 使用Transformers聊天 Docker Qwen家族的最新成員&#xff1a;Qwen2.5-VL 主要增強功能 強大的文檔解析功能&am…

HDMI接口設計

1. HDMI簡介 HDMI(High Definition Multimedia Interface)高清多媒體接口,是首個支持在單線纜上傳輸,不經過壓縮的全數字高清晰度、多聲道音頻和智能格式與控制命令數據的數字接口。這個接口可以同時傳輸視頻信號、音頻信號和控制信號。 從上圖里面可以看到HDMI有3組數據信號…

C/C++ JSON 庫綜合對比及應用案例(六)

第六部分&#xff1a;C/C JSON 庫綜合對比及應用案例 &#x1f4e2; 快速掌握 JSON&#xff01;文章 視頻雙管齊下 &#x1f680; 如果你覺得閱讀文章太慢&#xff0c;或者更喜歡 邊看邊學 的方式&#xff0c;不妨直接觀看我錄制的 JSON 課程視頻&#xff01;&#x1f3ac; …

LXC 導入(Rockylinux,almalinux,oraclelunx,debian,ubuntu,openEuler,kail,opensuse)

前提要求 ubuntu下安裝lxd 參考Rockylinux下安裝lxd 參考LXC 源替換參考LXC 容器端口發布參考LXC webui 管理<