C語言:指針(二)

目錄

  • 1.數組名的理解
  • 2.使用指針訪問數組
  • 3.一維數組傳參的本質
  • 4.二級指針
  • 5.指針數組
  • 6.字符指針變量
  • 7.數組指針變量
  • 8.二維數組傳參的本質
  • 9.函數指針變量
  • 10.函數指針數組
  • 11.回調函數
  • 12.qsort函數
  • 13.使用回調函數模擬實現qsort函數

1.數組名的理解

int main() {int arr[] = { 1,2,3 };printf("%p\n", &arr[0]);printf("%p\n", arr);return 0;
}

在這里插入圖片描述
從結果可以看出,&arr[0] == arr,這是用為數組名就是地址,而且是首元素的地址
但是,arr作為數組名在兩種情況下不表示首元素的地址:

  • sizeof(數組名),sizeof中單獨存放數組名表示求整個數組的大小,單位是字節
  • &arr,&arr是&后面直接加上一個數組名,它表示整個數組的地址。(&arr在數值上可能與&arr[0]相同,但是本質上是不一樣的,即&arr[0] == arr != &arr )
    除此之外,數組名都表示首元素的地址。
    在這里插入圖片描述
    其實arr與&arr的區別不在于直接打印的數值上,而在于運算上,
int main() {int arr[] = { 1,2,3 };printf("%p\n", &arr[0]);printf("%p\n", &arr[0]+1);printf("%p\n", arr);printf("%p\n", arr+1);printf("%p\n", &arr);printf("%p\n", &arr+1);return 0;
}

在這里插入圖片描述
可以看出,arr和&arr[0]加一的結果都是跳過4個字節,而&arr則跳過12個字節(E8-F4 =(15 * 16 ^ 1 + 4 * 16 ^ 0)- ( 14*16^1 + 8 *16 ^0) =12).
&arr表示整個數組,加一表示跳過整個數組,數組一共3個int類型的數據,所以一次跳過12個字節。

2.使用指針訪問數組

數組可以使用下標引用操作符來訪問,比如:

int ret = arr[9];

既然數組名相當于地址,那么還可以這樣訪問:

int* p = &arr[9];
int ret = *p;

3.一維數組傳參的本質

以前將數組作為參數傳遞給函數時需要將數組的數據個數一起傳遞給函數,那么,不傳遞數據個數可以嗎?

void test(int arr[]) {int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz2);
}
int main() {int arr[] = {1,2,3,4,5};int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}

在這里插入圖片描述
從結果來看是不行的,
其實,將數組作為參數是將數組的首元素的地址作為參數傳遞給函數
所以,在函數內部使用sizeof(arr)實際上計算的是一個地址的大小。正因為參數部分的本質是指針,所以不能不傳數據個數

4.二級指針

指針變量也是變量,是變量就有地址,所以二級指針是用來存放一級指針變量的地址的
在這里插入圖片描述
畫圖說明:
在這里插入圖片描述
對于二級指針的運算:

  • *ppa通過對ppa中的地址解引用,找到的是pa,*ppa訪問的就是p
  • **ppa先對ppa解引用得到pa然后對pa解引用得到a

5.指針數組

存放整型的數組叫做整型數組
存放字符的數組叫做字符數組
那么存放指針的數組就叫做指針數組

在這里插入圖片描述

6.字符指針變量

在指針的類型中有一種指針類型叫做字符指針char*
在這里插入圖片描述
還有一種使用方法:

int main() {const char* p = "abcdef";printf("%s\n", p);return 0;
}

這種表示方法相當于將字符串看作為一個字符數組,指針變量p存放的不是字符串而是首字符’a‘的地址。
如果兩個指針指向同一個字符串,那么不會開辟兩個空間來存放,也就是說兩個指針指向的是同一個內存

7.數組指針變量

存放整型數據地址的指針叫做整型指針
存放字符型數據的指針叫做字符指針
那么存放數組的地址的指針叫做數組指針

指針數組是數組,而數組指針是變量

int (*P)[5];

p先于*結合說明p是一個指針,再于【】和 int結合說明他是一個數組指針,數組元素類型是int。

數組自指針的初始化:

int main() {int arr[10] = { 0 };int(*p)[10] = &arr;return 0;
}

在這里插入圖片描述
&arr == p

8.二維數組傳參的本質

當我們將二位數組作為參數傳遞給函數時,其實傳遞的是第一行的地址(不是第一個元素的地址)

void test(int(*p)[3], int r, int c) {for (int i = 0; i < r; i++) {for (int j = 0; j < c; j++) {printf("%d ", *(*(p + i) + j));}printf("\n");}
}
int main() {int arr[2][3] = { {1,2,3},{2,3,4} };test(arr, 2, 3);return 0;
}

因為傳遞的是第一行元素的地址,那么該地址就該用函數指針來接收。
在這里插入圖片描述

9.函數指針變量

函數也有地址,那么該地址就可以使用指針變量來接受,那么該指針變量就是函數指針變量。

int (*p)(int, int);

在這里插入圖片描述
可以看出函數名就是函數的地址,也可以使用&函數名來獲得函數的地址。
要將函數的地址存放起來,就可以使用函數指針變量
在這里插入圖片描述
可以使用函數指針變量來調用函數

void test() {printf("haha\n");
}
int main() {int(*p)() = test;p();return 0;
}

在這里插入圖片描述

10.函數指針數組

函數指針是用來存放函數的地址的,那么有很多函數,要將它們的地址存放在一起,那么就可以使用函數指針數組。

int (*p[10])(int, int);

p先于【】結合說明是一個數組,那么數組的內容就是int (*)().

int Add(int x, int y) {return x + y;
}
int Sub(int x, int y) {return x - y;
}
int Mul(int x, int y) {return x * y;
}
int Div(int x, int y) {return x / y;
}
void Menu() {printf("**************************\n");printf("*****1.加法    2.減法*****\n");printf("*****3.乘法    4.除法*****\n");printf("*****0.退出          *****\n");printf("**************************\n");
}
int main() {int n = 0;int num1 = 0, num2 = 0;int(*p[5])(int, int) = { 0,Add,Sub,Mul,Div };do {Menu();printf("請輸入要選擇的功能:>");scanf("%d", &n);if (n >= 1 && n <= 4) {printf("\n請輸入兩個數用于計算:>");scanf("%d%d", &num1, &num2);printf("\n計算結果:%d\n", (*p[n])(num1, num2));}else if (n == 0) {printf("已退出\n");break;}else {printf("選擇錯誤,重新選擇:>");}} while (n);return 0;
}

這個代碼實現了一個簡單的計算器。
int( * p[5])(int, int) = { 0,Add,Sub,Mul,Div };
這段代碼就是將四個函數的地址放在一個函數指針數組里面
( * p[n])(num1, num2);
這段代碼函數指針數組來調用函數n表示想調用哪個函數,num1和num2就是傳遞給函數的參數

11.回調函數

回調函數就是一個通過函數指針調用的函數
如果將函數的指針作為一個參數傳遞給另一個函數,但這個指針被用來調用其所指的函數時,被調用的函數就是回調函數。

void test2() {printf("hahaha\n");
}
void test1(void (*test2)()) {printf("haha\n");test2();
}
int main() {test1(test2);return 0;
}

在這里插入圖片描述
在main函數中,將test2的地址傳遞給test1,然后test1用函數指針變量來接收,然后調用test2函數,那么test2函數就是回調函數。

12.qsort函數

qsort函數的功能是將任意類型的數據排列,底層原理是快速排序。

#include<stdlib.h>void com_arr(const void* p1, const void* p2) {return *(int*)p1 - *(int*)p2;
}void print(int arr[], int sz) {for (int i = 0; i < sz; i++) {printf("%d ", arr[i]);}printf("\n");
}
int main() {int arr[] = { 5,2,1,7,3,4,6,14,8 };int sz = sizeof(arr) / sizeof(arr[0]);print(arr, sz);qsort(arr, sz, 4, com_arr);print(arr, sz);return 0;
}

在這里插入圖片描述
qsort函數需要4個參數,第一個參數是數組首元素的地址,第二個參數是數組中元素的個數,第三個參數是數組中數據類型的大小,第四個參數是一個函數,作用是實現排序這種數據的方法。
在上述代碼中排序整型數組中的數據,那么第四個參數就可以讓兩個整數相減,返回負數表示第一個元素小于第二個元素,反之大于。

13.使用回調函數模擬實現qsort函數

我們可以采用冒泡排序的方式來實現qsort函數

int Method(const void* p1, const void* p2) {//用以判斷兩個數時候該交換return (*(int*)p1 - *(int*)p2);
}void Swap(void* p1, void* p2 ,int sz) {for (int i = 0; i < sz; i++) {char tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}
void Maopao(void* arr, int sz, size_t num, int (*method)(void*, void*)) {for (int i = 0; i < sz - 1; i++) {for (int j = 0; j < sz - 1 - i; j++) {if (method((char*)arr + j * num, (char*)arr + (j+1) * num) > 0){Swap((char*)arr + j * num, (char*)arr + (j+1) * num, num);}}}
}
int main() {int arr[] = { 4,2,6,1,7,5,9,8 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++) {printf("%d ", arr[i]);}printf("\n");Maopao(arr, sz, sizeof(arr[0]), Method);for (int i = 0; i < sz; i++) {printf("%d ", arr[i]);}return 0;
}

在這里插入圖片描述

/考研勢在必行/

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

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

相關文章

VBA將當前打開的表格生成PDF圖片

前言 VBA將當前的表格存儲成PDF文件進行存儲 代碼 Sub ExportToPDF()Dim FilePath As StringDim FileName As StringDim ExportRange As Range 設置導出文件路徑及名稱FilePath "D:\Users\"FileName "ExportedPDF" 設置導出區域范圍Set ExportRange Ra…

Unity(第十八部)物理力學,碰撞,觸發、關節和材質

1、重力 剛體組件 英文中文描述RigidBody剛體組件physics->rigidbody &#xff0c;剛體組件使一個物體有了質量&#xff0c;重力等。&#xff0c;use gravity 勾選后&#xff0c;物體才會受到重力&#xff0c;會自動下落&#xff0c;取消勾選就不會。&#xff0c;&#xf…

RTCA DO-178C 機載系統和設備認證中的軟件注意事項 - 目錄

本文為DO-178C標準目錄&#xff0c;可點擊以下對應章節直接跳轉至具體內容。 1.0 介紹 INTRODUCTION 2.0 軟件開發的系統相關性 SYSTEM ASPECTS RELATING TO SOFTWARE DEVELOPMENT 3.0 軟件生命周期 SOFTWARE LIFE CYCLE 4.0 軟件計劃過程 SOFTWARE PLANNING PROCESS 5.0 …

selenuim[1]($x(‘xpath語法’)、WebDriverWait())

文章目錄 初學selenuim記錄1、執行driver webdriver.Chrome()后很久才打開瀏覽器2、瀏覽器多元素定位 $x(‘xpath語法’)3、打開瀏覽器driver.get("網址")執行了很久才開始定位元素&#xff1a;等待&#xff08;1&#xff09;driver.set_page_load_timeout(t)&#…

超越CPU和GPU:引領AI進化的LPU

什么是CPU CPU&#xff08;Central Processing Unit&#xff09;是由數十億個晶體管構成的&#xff0c;可以擁有多個處理核心&#xff0c;通常被稱為計算機的“大腦”。它對所有現代計算系統至關重要&#xff0c;因為它執行計算機和操作系統所需的命令和進程。CPU在決定程序運…

【Linux C | 網絡編程】gethostbyaddr 函數詳解及C語言例子

&#x1f601;博客主頁&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客內容&#x1f911;&#xff1a;&#x1f36d;嵌入式開發、Linux、C語言、C、數據結構、音視頻&#x1f36d; &#x1f923;本文內容&#x1f923;&a…

JavaSE面試——hashcode和equals

對象調用 hashCode 方法后&#xff0c;會返回一串 int 類型的數字碼 java 規定&#xff1a; 1. 兩個對象的 hashCode() 相等&#xff0c;那他們的 equals() 不一定相等 2. 兩個對象的 equals() 相等&#xff0c;那他們的 hashCode() 必定相等 3. 重寫 equals() 方法時一定要…

三天學會阿里分布式事務框架Seata-SpringCloud Alibaba分布式基礎案例搭建

鋒哥原創的分布式事務框架Seata視頻教程&#xff1a; 實戰阿里分布式事務框架Seata視頻教程&#xff08;無廢話&#xff0c;通俗易懂版&#xff09;_嗶哩嗶哩_bilibili實戰阿里分布式事務框架Seata視頻教程&#xff08;無廢話&#xff0c;通俗易懂版&#xff09;共計10條視頻&…

日志到filebeat-->logstash-->elastic-->kibana

1、日志到filebeat。 cat /etc/filebeat/filebeat.yml filebeat.inputs: - type: syslog format: rfc3164 protocol.udp: host: "0.0.0.0:514" output.logstash: hosts: ["localhost:5044"] 驗證方式: tcpdump -i 網卡名稱 udp port 514 2、…

NLog條件配置——實現將包含某個特定字符串日志寫入指定文件

需求產生緣由 在開發中為了了解程序在運行的內存狀態并記錄下來&#xff0c;以便出問題時判斷是不是與內存相關。于是實時采集了開發程序需要的內存信息。但采集的內存信息在存儲時&#xff0c;以NLog中的Trace級別來存儲的話&#xff0c;會與程序其它Trace級別的日志都記錄在…

瑞吉蒼穹外賣如何拓展?已經經過不同公司多輪面試。項目中會問到哪些問題?以及問題如何解決?

別催了&#xff0c;別催了&#xff0c;先收藏吧。 作者大大正在加班加點完成。 文章會盡快發布&#xff0c;關注收藏&#xff0c;盡請期待。 想要加入并查閱作者的知識庫可以聯系作者 不要白嫖&#xff0c;通過后&#xff0c;附上關注和收藏截圖。 已有眾多小伙伴加入 目前…

QtCreator報Failed to parse qmlimportscanner output解決

錯誤如下: 定位錯誤位置 增加錯誤信息打印 打印執行命令 執行打印輸出的命令,成功返回JSON 但輸出的JSON對象不是json格式,而是命令 增加$$成功輸出JSON 使用QtCreator12編譯一次后,再使用QtCreator13成功編譯通過,問題解決

初學者如何使用QT新建一個包含UI界面的C++項目

文章目錄 一、下載并安裝QT51、下載安裝包2、注冊/登錄賬號3、安裝qt6 二、新建QT Widget項目1、新建項目并且運行2、易錯點&#xff1a;可能運行成功得到UI界面但是會報錯&#xff08;原因是使用了中文路徑&#xff09; 一、下載并安裝QT5 1、下載安裝包 進入下載網址 Windo…

C語言系列16——C語言標準庫深度揭秘:探索其內核與應用

目錄 寫在開頭1.C語言標準庫概覽1.1 定義與組成1.2 歷史發展簡述1.3 C標準庫與C標準庫的關系 2.標準庫的核心組件2.1 輸入輸出庫&#xff08;stdio.h&#xff09;2.1.1 定義與作用2.1.2 核心函數和用法2.1.3 常見問題與解決方案 2.2 字符串和字符處理&#xff08;string.h &…

面試經典150題【41-50】

文章目錄 面試經典150題【41-50】49.字母異位詞分組1. 兩數之和202.快樂數219. 存在重復元素II128.最長連續序列228. 匯總區間56.合并區間&#xff08;華為面試題&#xff09;57.插入區間452.用最少的箭引爆氣球20.有效的括號 面試經典150題【41-50】 49.字母異位詞分組 用這種…

今日話題:---自卑

自卑是一種普遍存在的心理現象&#xff0c;它可能源于個人對自身能力、外貌、社會地位等方面的不滿意或不自信。自卑感可能會導致消極的情緒和行為&#xff0c;如焦慮、抑郁、逃避現實等。然而&#xff0c;適度的自卑感也可能激發個人努力提升自己&#xff0c;從而實現自我成長…

TensorBoard的使用,add_image()的使用。

在TensorBoard中&#xff0c;add_image()函數用于將圖像數據添加到可視化中。它可以用于顯示模型輸入、輸出、中間特征圖等圖像數據&#xff0c;以幫助開發者理解模型的運行情況。 add_image()的用法&#xff1a; 使用ctrl點擊add_image() 注意&#xff1a;圖片類型要求為 t…

機器學習筆記 YOLOv9模型相關論文簡讀

一、YOLOv9簡述 自 2015 年 Yolov1 推出以來,已經出現了多個版本。 基于Darknet的YOLOv2、YOLOv3和YOLOv4 YOLOv5 YOLOv8 基于 Ultralytics。 SCALED-YOLOv4 使用 Pytorch 而不是 Darknet。 YOLOR是YOLOv4的改進。 YOLOX是YOLOv3的改進。 YOLOv6專注于工業應用。 YOLOv7 來自 …

【實戰-08】 flink自定義Map中的變量的行為

場景 自定義Map或者別的算子的時候&#xff0c;有時候需要定義一些類變量&#xff0c;在flink內部高并發的情況下需要正確理解這些變量的行為 代碼 package com.pg.function;import org.apache.flink.api.common.functions.MapFunction; import org.apache.flink.api.common…

哇去,有了這篇文章,項目中引入了再多的字體包,我都不怕了!!!

通常情況下&#xff0c;我們在開發一個新項目的時候&#xff0c;項目那邊通常都會提供一些項目所需的字體包&#xff0c;來滿足項目對字體展示的特殊需求。 這部分大家都比較熟悉&#xff0c;就不詳細講了&#xff0c;直接上代碼&#xff1a; /* 引入字體包 */ font-face {fo…