【時時三省】(C語言基礎)通過指針引用數組

山不在高,有仙則名。水不在深,有龍則靈。 ----CSDN 時時三省

數組元素的指針

一個變量有地址,一個數組包含若干元素,每個數組元素都在內存中占用存儲單元,它們都有相應的地址。指針變量既然可以指向變量,當然也可以指向數組元素(把某一元素的地址放到一個指針變量中)。所謂數組元素的指針就是數組元素的地址。可以用一個指針變量指向一個數組元素。

例如:

int a [ 10 ] = ( 1,3,5,7,9,11,13,15,17,19 );

int * p ;

p = & a [ 0 ];

以上是使指針變量p指向a數組的第0號元素。

引用數組元素可以用下標法(如a [ 3 ]),也可以用指針法,即通過指向數組元素的指針找到所需的元素。使用指針法能使目標程序質量高(占內存少,運行速度快)。

C語言中,數組名(不包括形參數組名)代表數組中首元素(即序號為0的元素)的地址。因此,下面兩個語句等價:

p=&a[0];

p=a;

注意:程序中的數組名不代表整個數組,只代表數組首元素的地址。上述“p?= a;"的作用是“把a數組的首元素的地址賦給指針變量p”,而不是“把數組a各元素的值賦給p”

在定義指針變量時可以對它初始化,如:

int p &a [ 0 ];

它等效于下面兩行:

int *p;

p=&a[0];

當然定義時也可以寫成

int * p = a ;

它的作用是將a數組首元素(即a [ 0 ])的地址賦給指針變量p(而不是賦值給*p)。

在引用數組元素時指針的運算

在引用數組元素時常常會遇到指針的算術運算。有人會提出問題:對數值型數據進行算術運算(加、減、乘、除等)的目的和含義是清楚的,而在什么情況下需要用到對指針型數據的算術運算呢?其含義是什么?

前已反復說明指針就是地址。對地址進行賦值運算是沒有問題的,但是對地址進行算術運算是什么意思呢?顯然對地址進行乘和除的運算是沒有意義的,實際上也無此必要。那么,能否進行加和減的運算?答案是:在一定條件下允許對指針進行加和減的運算。

那么,在什么情況下需要而且可以對指針進行加和減的運算呢?回答是:當指針指向數組元素的時候。譬如,指針變量p指向數組元素a [ 0 ],我們希望用p +1表示指向下一個元素a1。如果能實現這樣的運算,就會對引用數組元素提供很大的方便。

在指針已指向一個數組元素時,可以對指針進行以下運算:

加一個整數(用+或+ =),如p +1;

減一個整數(用-或- =),如p -1;

自加運算,如p++,++p;

自減運算,如p--,--p。

兩個指針相減,如pl -p2(只有pl和p2都指向同一數組中的元素時才有意義)。

分別說明如下:

( 1 )如果指針變量p已指向數組中的一個元素,則p +1指向同一數組中的下一個元素,p-1指向同一數組中的上一個元素。注意:執行p +1時并不是將p的值(地址)簡單地加1,而是加上一個數組元素所占用的字節數。例如,數組元素是float型,每個元素占4個字節,則p +1意味著使p的值(是地址)加4個字節,以使它指向下一元素。

p +1所代表的地址實際上是p +1×d,d是一個數組元素所占的字節數(在Visual C++中,對int型,d = 4,對float和long型,d = 4;對char型,d = 1 )。若p的值是2000,則p +1的值不是2001,而是2004。

系統怎么知道要把這個1轉換為4,然后與p的值相加呢?不要忘記,在定義指針變量時必須要指定基類型,如:

float * p;

現在p指向float型的數組元素,在執行++p時,系統會根據p的基類型為float型而將其值加4,這樣,p就指向float型數組的下一個元素。如果p原來指向a [ 0 ],執行++p后p的值改變了,在p的原值基礎上加d,這樣p就指向數組的下一個元素a [ 1 ]。

( 2 )如果p的初值為& a [ 0 ],則p + i和a + i就是數組元素a數組a [i]的地址,或者說,它們指向a數組序號為i的元素,這里需要注意的是a代表數組首元素的地址,a +1也是地址,它的計算方法同p +1,即它的實際地址為a +1×d。

( 3 ) * ( p + i )或* ( a + i )是p + i或a + i所指向的數組元素,即a [ i ]。例如,* ( p + 5 )或* ( a + 5 )就是a[?5 ],即:*(p+5),*(a+5)和a[5]三者等價。實際上,在編譯時,對數組元素a[i]就是按* ( a + i )處理的,即按數組首元素的地址加上相對位移量得到要找的元素的地址,然后找出該單元中的內容。若數組a的首元素的地址為1000,設數組為float型,則a [ 3 ]的地址是這樣計算的:1000 + 3×4 = 1012,然后從1012地址所指向的float型單元取出元素的值,即a [ 3 ]的值。

說明:[ ]實際上是變址運算符,即將a [ i ]按a + i計算地址,然后找出此地址單元中的值。

( 4 )如果指針變量pl和p2都指向同一數組中的元素,如執行p2 -p1,結果是p2 - p1的值(兩個地址之差)除以數組元素的長度。假設,p2指向實型數組元素a [ 5 ],p2的值為2020;pl指向a [ 3 ],其值為2012,則p2 - pl的結果是( 2020-2012 )/ 4 = 2。這個結果是有意義的,表示p2所指的元素與pl所指的元素之間差2個元素。這樣,人們就不需要具體地知道pl和p2的值,然后去計算它們的相對位置,而是直接用p2 - p1就可知道它們所指元素的相對距離。

注意:兩個地址不能相加,如pl + p2是無實際意義的。

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

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

相關文章

【WEB】Polar靶場 21-25題 詳細筆記

二十一.php very nicephp又是你 ,但是經過這么多次折磨后我感覺我已經有一點抗性了老規矩,先看知識點PHP 序列化是將 PHP 變量(如對象、數組)轉換為字符串的過程,便于存儲或傳輸。反序列化則是將字符串還原為原始變量。這在緩存、…

【Guava】1.0.設計虛擬機的方向

【Guava】1.0.設計虛擬機的方向虛擬機是什么?棧式虛擬機棧式虛擬機的優缺點題外話虛擬機是什么? 虛擬機(VirtualMachine, VM)是一種計算機程序或系統,它通過軟件模擬物理計算機的硬件運行環境,使得多個操作…

[附源碼+數據庫+畢業論文]基于Spring+MyBatis+MySQL+Maven+jsp實現的高校實驗室資源綜合管理系統,推薦!

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術,讓傳統數據信息的管理升級為軟件存儲,歸納,集中處理數據信息的管理方式。本高校實驗室資源綜合管理系統就是在這樣的大環境下誕生,其可以幫助管理者在短時間內處理完畢龐大…

Spring Boot:影響事務回滾的幾種情況

一、Controller 捕獲異常導致事務失效 需求 我們有一個用戶注冊服務,注冊時需要: 創建用戶賬戶分配初始積分發送注冊通知 這三個操作需要在同一個事務中執行,任何一步失敗都要回滾。 錯誤示例:Controller 捕獲異常導致事務失效 Re…

如何避免分布式爬蟲被目標網站封禁?

在分布式爬蟲的大規模數據采集場景中,避免被目標網站封禁的核心邏輯是:通過技術手段模擬真實用戶行為,降低爬蟲行為的可識別性,同時建立動態適配機制應對網站反爬策略的升級。以下從請求偽裝、行為控制、資源管理、反爬對抗四個維…

Maven 打包排除特定依賴的完整指南(詳細方法 + 示例)

前言 在使用 Maven 構建 Java 項目時,我們常常需要對項目的打包過程進行精細化控制,尤其是希望排除某些特定的依賴庫。這可能是為了減小最終構建產物的體積、避免版本沖突,或者僅僅是為了滿足不同環境下的部署需求。 本文將詳細介紹如何在 Ma…

Terraform `for_each` 精講:優雅地自動化多域名證書驗證

大家好,在云原生和自動化運維的世界里,Terraform無疑是基礎設施即代碼(IaC)領域的王者。它強大的聲明式語法讓我們能夠輕松地描述和管理云資源。然而,即使是經驗豐富的工程師,在面對某些動態場景時也可能會…

C++標準庫中各種互斥鎖的用法 mutex

示例 僅供參考學習 #include <mutex> #include <shared_mutex> #include <thread> #include <chrono> #include <iostream> #include <vector>// // 1. std::mutex - 基本互斥鎖 // void basic_mutex_example() {std::mutex mtx;int cou…

Android Handler機制與底層原理詳解

Android 的 Handler 機制是跨線程通信和異步消息處理的核心框架&#xff0c;它構成了 Android 應用響應性和事件驅動模型的基礎&#xff08;如 UI 更新、后臺任務協調&#xff09;。其核心思想是 “消息隊列 循環處理”。 核心組件及其關系Handler (處理器): 角色: 消息的發送…

jQuery JSONP:實現跨域數據交互的利器

jQuery JSONP&#xff1a;實現跨域數據交互的利器 引言 隨著互聯網的發展&#xff0c;跨域數據交互的需求日益增加。在Web開發中&#xff0c;由于同源策略的限制&#xff0c;直接通過XMLHttpRequest請求跨域數據會遇到諸多問題。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 實現分布式鎖的優勢和劣勢

在分布式系統中&#xff0c;實現分布式鎖是確保多個節點間互斥訪問共享資源的一種常見需求。Redis 集群 和 zookeeper 都可以用來實現這一功能&#xff0c;但它們有著各自不同的優勢和劣勢。 CAP 理論&#xff1a; 在設計一個分布式系統時&#xff0c;一致性&#xff08;Consis…

如何備份vivo手機中的聯系人?

隨著vivo移動設備在全球設立7個研發中心&#xff0c;vivo正在進入更多的國家。如今&#xff0c;越來越多的人開始使用vivo手機。以vivo X100為例&#xff0c;它配備了主攝像頭和多個輔助攝像頭&#xff0c;提供多樣化的拍攝選項&#xff0c;并搭載了最新的FunTouch OS&#xff…

python腳本編程:使用BeautifulSoup爬蟲庫獲取熱門單機游戲排行榜

BeautifulSoup是一個便捷的解析html頁面元素的python庫&#xff0c;此處用來寫一個簡單的爬蟲批量抓取國內游戲資訊網站的近期熱門單機游戲排行榜。 網頁來源如下所示代碼 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面詳解:從傳統方式到現代配置系統

C#配置全面詳解&#xff1a;從傳統方式到現代配置系統 在軟件開發中&#xff0c;配置是指應用程序運行時可調整的參數集合&#xff0c;如數據庫連接字符串、API 地址、日志級別等。將這些參數從代碼中分離出來&#xff0c;便于在不修改代碼的情況下調整應用行為。C# 提供了多種…

數據中臺架構解析:湖倉一體的實戰設計

目錄 一、數據中臺與湖倉一體架構是什么 1. 數據中臺 2. 湖倉一體架構 3. 湖倉一體在數據中臺里的價值 二、湖倉一體架構的核心部件 1. 數據湖 2. 數據倉庫 3. 數據集成工具 4. 數據分析與處理引擎 三、湖倉一體架構實戰設計 1. 需求分析與規劃 2. 數據湖建設 3. …

SQL Server表分區技術詳解

表分區概述 表分區是將大型數據庫表物理分割為多個較小單元的技術,邏輯上仍表現為單一實體。該技術通過水平分割數據顯著提升查詢性能,尤其針對TB級數據表可降低90%的響應時間。典型應用場景包含訂單歷史表、日志記錄表等具有明顯時間特征的業務數據,以及需要定期歸檔的審計…

WHIP(WebRTC HTTP Ingestion Protocol)詳解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;詳解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一種基于 HTTP 的協議&#xff0c;用于將 WebRTC 媒體流推送到媒體服務器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是為簡化 WebRT…

圖像噪點消除:用 OpenCV 實現多種濾波方法

在圖像處理中&#xff0c;噪點是一個常見的問題。它可能是由于圖像采集設備的缺陷、傳輸過程中的干擾&#xff0c;或者是光照條件不佳引起的。噪點會影響圖像的質量和后續處理的效果&#xff0c;因此消除噪點是圖像預處理的重要步驟之一。本文將介紹如何使用 OpenCV 實現幾種常…

AI的Prompt提示詞:英文寫好還是中文好?

在與AI人大模型交互時,Prompt(提示詞)的質量直接決定了輸出的精準度和有效性。一個常見的問題是:究竟是用英文寫Prompt好,還是用中文寫更好?這并非一個簡單的二元選擇,而是涉及到語言模型的底層邏輯、表達的精確性以及個人使用習慣的綜合考量。 英文Prompt的優勢 模型訓…

react的條件渲染【簡約風5min】

const flag1true; console.log(flag1&&hello); console.log(flag1||hello); const flag20; console.log(flag2&&hello); console.log(flag2||hello); // &&運算符&#xff0c;如果第一個條件為假&#xff0c;則返回第一個條件&#xff0c;否則返回第二…