C語言之指針進階(3),函數指針


目錄

前言:

一、函數指針變量的概念

二、函數指針變量的創建

三、函數指針變量的使用

四、兩段特殊代碼的理解

五、typedef

六、函數指針數組

總結:


前言:

? ? ? ? 本文主要講述C語言指針中的函數指針,包括函數指針變量的概念、創建及使用。兩段特殊代碼的理解,typedef關鍵字的使用,以及函數指針數組的使用,最后還有一個代碼案例--計算器的實現。希望對大家有所幫助。


一、函數指針變量的概念

函數指針變量,是用于存儲函數地址的指針變量

那么,函數有地址嗎?函數名與地址有關嗎?

簡單測試一下:

我們發現:函數名和取地址函數名得到的地址是一樣的

函數名本身可以被視為一個地址,指向函數代碼的起始位置,這與&函數名一樣,使用起來并無區別


二、函數指針變量的創建

既然函數名和&函數名得到了函數的地址,我們要存儲這種地址,就需要創建函數指針變量

定義語法:函數返回類型(*變量名)(形參類型,形參類型)

如:

調試監視其值:

觀察類型我們可以得知,函數指針變量的類型就是:去掉變量名,剩下的就是函數指針變量的類型

函數指針類型解析:

int? (*pf4) (int x, int y)

  • int:pf4指向的函數類型
  • pf4:函數指針變量名,*表明其為指針變量
  • (int x, int y):pf4指向函數的參數類型和個數的交代


三、函數指針變量的使用

通過函數指針調用指針指向的函數

使用方法1:

該方法就是通過解引用指針,找到函數地址,然后傳入參數,接收返回值

使用方法2:

直接寫函數指針變量的變量名,然后傳入參數,這與直接寫函數名傳入參數是一樣的,因為該指針變量值就等于函數名的地址

其實方法1中,*pf前面的*號本身無實際作用

我們無論寫多少*號,結果是一樣的,編譯器沒有對這個符號進行相關操作,故相當于擺設了,不過為了提高可讀性,一般是寫一個*號

注意:*pf必須用括號括起來,因為左邊優先級高于*號,不加括號會被編譯器認為是解引用函數的返回值,而這是一個非法訪問


四、兩段特殊代碼的理解

1.( *(? void (*)()? ) 0 ) ()

請問這段代碼是什么意思?

這其實是一次函數調用的代碼,調用0地址處的函數

那么如何分析這段代碼呢,我們畫圖來理解:

注意:該代碼出自《C陷阱與缺陷》一書,情景是一位程序員需要寫一個獨立運行于某種微處理器上的C程序,當計算機啟動時,硬件將調用0地址處的子例程(函數)。于是設計出了這段代碼


2.void ( *signal( int , void(*)(int) ) )(int);

請問這段代碼是什么意思?

答案是:這是一個函數聲明。我們畫圖分析

以上難以理解的可能就是第3步,按照以往的理解,理論上函數的返回類型不應該寫在函數名前面嗎,也就是下面這樣

我們發現把 void(*)(int) 的返回類型寫在函數名前面,編譯器報錯了

這其實是語法規定的,函數指針作為返回類型,函數名需寫在類型的里面,也就是*號的旁邊,上面那種才是正確的寫法


五、typedef

我們發現上面那段代碼是不是較難看懂,如果能讓其與一般函數寫法一樣,也就是函數返回類型寫在前面就好了,這里就有一個方法,使用typedef重命名

typedef:對類型名進行重命名

例1:重命名unsigned int

例2:重命名數組指針

注意:數組指針重命名,重命名的名字要放在括號里邊

現在,就讓我們把void ( *signal( int , void(*)(int) ) )(int)進行重命名:

注意:與數組指針一樣,我們重命名的名字要放在類型里面,之后我們不管是以返回類型寫在函數名前面,還是以函數參數類型寫在參數里都可以,這樣看代碼是不是明朗了許多


六、函數指針數組

函數指針數組:存儲函數指針的數組,數組的元素都是一個個類型相同的函數指針

定義語法:見下面第二張圖

例如:

如上,兩個相同類型的函數指針變量我們可以定義,可是當相同類型的函數多起來后,如果我們需要儲存這些函數的地址,就需要數組來接收才方便了。

如:

注意:定義函數指針數組,數組放在數組類型里邊

調用數組元素時,就正常使用下標+傳入參數即可

如果覺得以上內容簡單,我們可以實現一個簡單案例

簡單計算器的實現:

#include <stdio.h>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.Add     2.Sub  **********\n");printf("**********  3.Mul     4.Div  **********\n");printf("**********      0.exit       **********\n");printf("***************************************\n");
}int main()
{int(*pf_arr[5])(int, int) = { 0,Add,Sub,Mul,Div };int input = 0;do{menu();printf("請選擇:\n");scanf("%d", &input);if (input >= 1 && input <= 4){int a = 0;int b = 0;printf("請輸入兩個整數:\n");scanf("%d %d", &a, &b);printf("%d\n", pf_arr[input](a, b));}else if (input == 0){printf("程序退出\n");break;}else{printf("選擇錯誤,請重新選擇:\n");}} while (input);return 0;
}


總結:

????????以上就是本文的全部內容了,希望對大家有所幫助,哪里有問題歡迎提出,感謝大家的支持

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

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

相關文章

【面試干貨】事務的并發問題(臟讀、不可重復讀、幻讀)與解決策略

【面試干貨】事務的并發問題&#xff08;臟讀、不可重復讀、幻讀&#xff09;與解決策略 一、臟讀&#xff08;Dirty Read&#xff09;二、不可重復讀&#xff08;Non-repeatable Read&#xff09;三、幻讀&#xff08;Phantom Read&#xff09;四、總結 &#x1f496;The Begi…

Stable Diffusion——U-ViT用于擴散建模的 ViT 主干網

1.概述 擴散模型是最近出現的強大的深度生成模型&#xff0c;可用于生成高質量圖像。擴散模型發展迅速&#xff0c;可應用于文本到圖像生成、圖像到圖像生成、視頻生成、語音合成和 3D 合成。 除了算法的改進&#xff0c;骨干網的改進在擴散建模中也發揮著重要作用。一個典型…

nginx代理前端html

正常配置&#xff0c;通過www.example.com或192.168.20.12:80訪問server {listen 80;server_name example.com www.example.com;root /var/www/html;index index.html index.htm;location / {try_files $uri $uri/ 404;} }解釋&#xff1a; listen 80;&#xff1a;監聽 HTTP 端…

汽車R155法規中,汽車獲取到的VTA證書,E后面的數字表示什么意思?

標簽&#xff1a; 汽車R155法規中&#xff0c;汽車獲取到的VTA證書&#xff0c;E后面的數字表示什么意思&#xff1f;&#xff1b; 汽車&#xff1b;VTA認證; 有些廠商汽車拿到的VTA證書上面寫著E9&#xff0c; 有些廠商汽車拿到的VTA證書上面寫著E5&#xff0c;E9與E5有什么差…

嵌入式之音頻基礎知識

聲音特性 1、響度&#xff1a;人主觀上感覺聲音的大小&#xff08;俗稱音量&#xff09;&#xff0c;由“振幅”和人離聲源的距離決定&#xff0c;振幅越大響度越大&#xff0c;人和聲源的距離越小&#xff0c;響度越大&#xff1b; 2、音調&#xff1a;聲音的高低&#xff0…

多商戶消費券系統源碼(ThinkPHP+FastAdmin+微信公眾號)

打造智能促銷新體驗 一、引言&#xff1a;消費券系統的時代意義 在當今這個數字化高速發展的時代&#xff0c;電子商務和移動支付已經成為人們日常生活的重要組成部分。隨著市場競爭的加劇&#xff0c;多商戶消費券系統作為一種創新的促銷手段&#xff0c;正逐漸受到商家和消…

k8s筆記 | helm包管理

什么是Helm kubenetes包管理器&#xff0c;是查找&#xff0c;分享和使用軟件構件 kubernetes的最佳方式&#xff1b; 可以做什么 從頭開始創建新的chart將chart打包成歸檔(tgz)文件與存儲chart的倉庫進行交互與現有的kubernates集群中安裝和卸載chart管理與Helm一起安裝的 …

從零訓練yolov8

1.收集數據 2.數據標注 pip install labelimg3.劃分數據集 0.2的驗證機0.8的訓練集 import os from shutil import copyfile from sys import exit import randomsource r"D:\Data\imgs\screenc" \\ target_train r"D:\Data\imgs\datasets\mydata\images\t…

aws msk加密方式和問控制連接方式

msk加密方式 msk提供了兩種加密方式 靜態加密傳輸中加密 創建集群時可以指定加密方式&#xff0c;參數如下 aws kafka create-cluster --cluster-name "ExampleClusterName" --broker-node-group-info file://brokernodegroupinfo.json --encryption-info file:/…

Android四大組件 Broadcast廣播機制

一 概述 廣播 (Broadcast) 機制用于進程或線程間通信&#xff0c;廣播分為廣播發送和廣播接收兩個過程&#xff0c;其中廣播接收者 BroadcastReceiver 是 Android 四大組件之一。BroadcastReceiver 分為兩類&#xff1a; 靜態廣播接收者&#xff1a;通過 AndroidManifest.xm…

flutter 實現旋轉星球

先看效果 planet_widget.dart import dart:math; import package:flutter/material.dart; import package:vector_math/vector_math_64.dart show Vector3; import package:flutter/gestures.dart; import package:flutter/physics.dart;class PlanetWidget extends StatefulW…

echarts-樹圖、關系圖、桑基圖、日歷圖

樹圖 樹圖主要用來表達關系結構。 樹圖的端點也收symbol的調節 樹圖的特有屬性&#xff1a; 樹圖的方向&#xff1a; layout、orient子節點收起展開&#xff1a;initialTreeDepth、expandAndCollapse葉子節點設置&#xff1a; leaves操作設置&#xff1a;roam線條&#xff1a…

告別 Dart 中的 Future.wait([])

作為 Dart 開發人員&#xff0c;我們對異步編程和 Futures 的強大功能并不陌生。過去&#xff0c;當我們需要同時等待多個 future 時&#xff0c;我們依賴 Future.wait([]) 方法&#xff0c;該方法返回一個 List<T>。然而&#xff0c;這種方法有一個顯著的缺點&#xff1…

2、xss-labs之level2

1、打開頁面 2、傳入xss代碼 payload&#xff1a;<script>alert(xss)</script>&#xff0c;發現返回<script>alert(xss)</script> 3、分析原因 打開f12&#xff0c;沒什么發現 看后端源碼&#xff0c;在這form表單通過get獲取keyword的值賦給$str&am…

跑大模型的經驗

LLama2: 1. 使用torchrun來跑&#xff1a; torchrun --nproc_per_node 1 example_text_completion.py \--ckpt_dir llama-2-7b/ \--tokenizer_path tokenizer.model \--max_seq_len 128 --max_batch_size 4 關于集群分布式torchrun命令踩坑記錄&#xff08;自用&#xff09;…

【Vue】input框自動聚焦且輸入驗證碼后跳至下一位

場景&#xff1a;PC端 樣式&#xff1a; <div class"verification-code-input"><input v-model"code[index]" v-for"(_, index) in 5" :key"index" type"text" maxlength"1" input"handleInput(i…

渲染管線——應用階段

知識必備——CPU和GPU 應用階段都做了什么 應用階段為渲染準備了什么 1.把不可見的數據剔除 2.準備好模型相關數據&#xff08;頂點、法線、切線、貼圖、著色器等等&#xff09; 3.將數據加載到顯存中 4.設置渲染狀態&#xff08;設置網格需要使用哪個著色器、材質、光源屬性等…

說些什么好呢

大一&#xff1a;提前學C和C。學完語法去洛谷或者Acwing二選一&#xff0c;刷300道左右題目。主要培養編程思維&#xff0c;讓自己的邏輯能夠通過代碼實現出來。 現在對算法有點感興趣但是沒有天賦&#xff0c;打不了acm&#xff0c;為就業做準備咯。 大二(算法競賽)&#xff1…

常用損失函數學習

損失函數&#xff08;Loss Function&#xff09;&#xff0c;在機器學習和統計學中&#xff0c;是用來量化模型預測輸出與真實結果之間差異的函數。簡而言之&#xff0c;損失函數衡量了模型預測的好壞&#xff0c;目標是通過最小化這個函數來優化模型參數&#xff0c;從而提高預…

簡述js的事件循環以及宏任務和微任務

前言 在JavaScript中&#xff0c;任務被分為同步任務和異步任務。 同步任務&#xff1a;這些任務在主線程上順序執行&#xff0c;不會進入任務隊列&#xff0c;而是直接在主線程上排隊等待執行。每個同步任務都會阻塞后續任務的執行&#xff0c;直到它自身完成。常見的同步任…