C++中指针使用详解(3)数组、指针和函数参数传递的底层 ABI实现

要深入理解 数组、指针和函数参数传递 的底层 ABI(Application Binary Interface)实现,需要从以下几个维度出发进行学习:


一、什么是 ABI?

ABI 是编译器和操作系统之间的协定,规定了:

  • 函数如何调用(参数传递、返回值)
  • 栈帧布局(局部变量、返回地址、保存寄存器)
  • 调用约定(Calling Convention)
  • 数据的对齐方式(alignment)
  • 如何在内存中布局结构体、数组、类对象等

例如:x86_64 系统通常使用 System V AMD64 ABI


二、函数参数传递 ABI 行为:值 / 地址 / 数组

1. 普通变量(按值传递)

void foo(int a) {// 栈帧中的 a 是实参副本
}
  • 编译器会将 a 作为 整数寄存器(如 rdi)传入
  • 或在栈中开空间拷贝参数(当寄存器用完或大于特定大小)

2. 指针(传地址)

void foo(int* p) {*p = 10;
}
  • 指针 p 是 8 字节地址,通常放在寄存器(如 rdi
  • *p 会间接访问内存(间接寻址)

3. 数组参数(退化为指针)

void foo(int arr[]) {arr[0] = 10;
}
  • int arr[] 会被 退化为 int* arr
  • ABI 上是 按指针传递

三、C++ 底层函数调用过程(以 x86_64 System V 为例)

调用 foo(int a, int* p) 时的流程(简化):

main():a = 42;int* p = &a;call foo(a, p)

底层汇编(伪代码):

mov edi, 42          ; 第一个参数 a → edi
mov rsi, &a          ; 第二个参数 p → rsi
call foo

四、函数栈帧结构(以 GCC / x86_64 为例)

一个函数的栈帧通常如下:

 ┌───────────────┐ ← 高地址│ 返回地址      │ ← 调用者压入│ old %rbp      │ ← 保存上层基址│ 参数备份/局部变量 ││ 临时寄存器保存 │└───────────────┘ ← %rsp 栈顶

调用过程:

  • call foo → 跳转并压入返回地址
  • push %rbp → 建立新的基址指针(%rbp)
  • sub rsp, n → 为局部变量分配空间

五、数组传值传引用的差异 ABI 视角下分析

1. 按值传递数组(不推荐)

void foo(int arr[5]) { ... } // 实际变为 int* arr
  • 编译器不会复制整个数组
  • 传的是指针地址
  • 在函数内对 arr[i] 的修改会影响外部

2. 真正的数组按值传递(必须用 std::array 或结构体包装)

struct ArrWrap {int arr[5];
};void foo(ArrWrap a);
  • 编译器会 完整拷贝结构体 到寄存器或栈
  • 不会影响原数组内容

六、C++ 对象参数 ABI 行为(指针/引用/拷贝)

参数类型ABI 表现
T可能按值复制进栈或寄存器
T&传指针,指向原对象
T*明确传地址
const T&仍然传地址,只是禁止修改

七、数组和指针的底层行为对比

void foo(int* p);    // 编译器看作地址传递
void bar(int arr[10]); // 实质上也是 int* arr

举例说明区别:

int arr[10];
foo(arr); // arr 退化为 &arr[0]
  • sizeof(arr) 是 40
  • sizeof(p) 是 8(在 64 位系统)
void size_test(int* p, int arr[10]) {cout << sizeof(p) << endl;   // 8cout << sizeof(arr) << endl; // 8(退化后)
}

八、调试验证:GCC 下使用 objdumpgdb

编译为汇编查看 ABI 细节:

g++ -O0 -S main.cpp -o main.s

或者用 gdb 单步跟踪:

gdb ./a.out
(gdb) break foo
(gdb) run
(gdb) info registers

九、结构体中的数组传递 ABI 规则

struct Data {int x;int arr[4];
};void process(Data d); // 会按值拷贝整个结构体(如果不大)

如果结构体很大,则:

  • 编译器会在 caller 中分配临时内存
  • 传递 指向该内存的隐藏指针

十、小结图示(建议结合图)

函数参数 ABI 层调用过程:main:┌─────────────┐│ 栈变量 a    │ ← &a└─────────────┘│▼
foo(a, &a):┌──────────────┐│ 寄存器传参   │ ← rdi = a, rsi = &a│ 栈帧建立     ││ 局部变量空间 │└──────────────┘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【RustDesk 】中继1:压力测试 Python 版 RustDesk 中继服务器

测试 Python 版 RustDesk 中继服务器 测试我们实现的中继服务器有几种方法,从简单到复杂依次如下: 1. 基本连接测试客户端 创建一个简单的测试客户端来验证中继服务器的基本功能: 2. 用两个测试客户端测试中继功能 要测试完整的中继功能,你需要运行两个客户端实例来模拟…

Spring Boot集成Spring Cloud 2024(不使用Feign)

本文介绍Spring Boot集成Spring Cloud 2024&#xff0c;且不使用Feign&#xff0c;而是采用Spring 6自带的HttpExchange方式进行服务调用的详细步骤&#xff1a; 环境准备 Spring Boot版本&#xff1a;推荐使用Spring Boot 3.4.1及以上版本&#xff0c;以更好地与Spring Clou…

vue中$set原理

Vue 中的 $set 方法&#xff08;Vue.set&#xff09;主要用于 向响应式对象中添加一个新的属性&#xff0c;并确保这个新属性是响应式的&#xff0c;能够触发视图更新。 &#x1f4cc; 背景问题&#xff1a;为什么需要 $set&#xff1f; 在 Vue 2 中&#xff0c;直接给对象新增…

Superset二次开发之深度解读系列:1.概述

Apache Superset 是一款现代化的企业级商业智能 Web 应用程序&#xff0c;专为数据探索和可视化而设计。本概述介绍了 Superset 的架构、核心组件和主要功能&#xff0c;以帮助开发人员了解该系统的工作原理。 What is Apache Superset? Apache Superset 是一个开源数据探索…

Linux系统之elfedit详解

elfedit 是一个用于修改 ELF&#xff08;可执行与可链接格式&#xff09;文件头的工具。它允许用户根据指定的条件&#xff08;如机器类型、文件类型、操作系统/ABI&#xff09;匹配并更新 ELF 文件的头部信息。支持 32 位和 64 位 ELF 文件&#xff0c;以及包含 ELF 文件的归档…

前端HTML基础知识

1.HTML介绍 HTML(HyperText Markup Language&#xff0c;超文本标记语言)是构成网页的基本元素&#xff0c;是一种用于创建网页的标准化标记语言。HTML不是一种编程语言&#xff0c;而是一种标记语言&#xff0c;通过标签来描述网页的结构和内容。 超文本&#xff1a;超文本是…

【IP101】图像滤波技术详解:从均值滤波到高斯滤波的完整指南

&#x1f31f; 图像滤波魔法指南 &#x1f3a8; 在图像处理的世界里&#xff0c;滤波就像是给图片"美颜"的魔法工具。让我们一起来探索这些神奇的滤波术吧&#xff01; &#x1f4d1; 目录 1. 均值滤波&#xff1a;图像的"磨皮"大法2. 中值滤波&#xff1…

LINE FRIENDS 正式与 Walrus 合作,全新 AI 驱动的游戏即将上线

风靡全球的 LINE FRIENDS 角色即将以“minini”迷你造型登陆 Walrus&#xff0c;虽然尺寸更小&#xff0c;但承诺带来“大”动作。IPX&#xff08;LINE FRIENDS 背后的公司&#xff09;打造了《minini universe: ROOM》游戏&#xff0c;这是一款基于其 minini 系列角色的多链游…

2025年信息素养大赛C++算法创意实践挑战赛初赛样题及答案解析(小学组)

一、选择题 1、下列代码&#xff0c;能够输出 hello world 的是_____ A. cout (hello world) B. cout << hello world C. cout:hello world D. cout << "hello world"; 答案&#xff1a;D 解析&#xff1a;cout输出的文本内容要用双引号引起来 2、…

[c语言日寄]检查环形链表

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

黄雀在后:外卖大战新变局,淘宝+饿了么开启电商大零售时代

当所有人以为美团和京东的“口水战”硝烟渐散&#xff0c;外卖大战告一段落时&#xff0c;“螳螂捕蝉&#xff0c;黄雀在后”&#xff0c;淘宝闪购联合饿了么“闪现”外卖战场&#xff0c;外卖烽火再度燃起。 4 月30日&#xff0c;淘宝天猫旗下即时零售业务“小时达”正式升级…

如何在uni-app中自定义输入框placeholder的样式

在开发uni-app应用时&#xff0c;我们经常需要自定义输入框&#xff08;<input>&#xff09;的样式以匹配应用的整体设计。默认情况下&#xff0c;uni-app的输入框提供了一些基本的样式选项&#xff0c;但有时候我们需要更细致地控制输入框的每个部分&#xff0c;例如pla…

使用Node编写轻量级后端快速入门

使用Node编写轻量级后端快速入门 node 要作为轻量级后端需要下载一些对应模块可以参考下面命令。你可以借助 npm&#xff08;Node Package Manager&#xff09;来下载它们。 模块下载 express&#xff1a;这是一个广受欢迎的 Node.js Web 应用框架&#xff0c;能用于构建 Web…

从Markdown到专业文档:如何用Python打造高效格式转换工具

在技术写作、学术研究和企业报告领域,Markdown因其简洁高效的特性广受开发者喜爱。但当需要输出正式文档时,Word和PDF格式仍是行业标准。传统解决方案往往存在样式丢失、代码排版混乱、批量处理困难等痛点。本文将揭秘如何用Python构建一个支持多主题、保留代码高亮、自动生成…

【docker学习笔记】如何删除镜像启动默认命令

一些镜像会在它打镜像时&#xff0c;加入一些默认的启动命令&#xff0c;可以通过docker inspect \<image id\>来查看Entrypoint。如下图&#xff0c;docker run启动时&#xff0c;会默认执行 "python3 -m vllm.entrypoints.openai.api_server" 如果不想执行&…

任意无人机手柄链接Unity-100元的凤凰SM600手柄接入Unity Input System‌

网上教程真少&#xff01;奋发图强自力更生&#xff01;2025.5.1 目前有用的链接&#xff1a; unity如何添加自定义HID设备&#xff0c;自己开发的手柄如何支持unity。 - 哔哩哔哩 HID Support | Input System | 1.0.2 官方教程 https://zhuanlan.zhihu.com/p/503209742 分…

2024睿抗CAIP-编程技能赛-本科组(省赛)题解

蓝桥杯拿了个省三&#xff0c;天梯没进1队&#xff0c;睿抗是我最后的机会 RC-u4 章鱼图的判断 题目描述 对于无向图 G ( V , E ) G(V,E) G(V,E)&#xff0c;我们定义章鱼图为&#xff1a; 有且仅有一个简单环&#xff08;即没有重复顶点的环&#xff09;&#xff0c;且所…

Java 泛型参数问题:‘ResponseData.this‘ cannot be referenced from a static contex

问题与处理策略 问题描述 Data AllArgsConstructor NoArgsConstructor public class ResponseData<T> {private Integer code;private String msg;private T data;public static final int CODE_SUCCESS 2001;public static final int CODE_FAIL 3001;public static …

用TCP实现服务器与客户端的交互

目录 一、TCP的特点 二、API介绍 1.ServerSocket 2.Socket 三、实现服务器 四、实现客户端 五、测试解决bug 1.客户端发送了数据之后&#xff0c;并没有响应 2.clientSocket没有执行close()操作 3.尝试使用多个客户端同时连接服务器 六、优化 1.短时间有大量客户端访…

鸟笼效应——AI与思维模型【84】

一、定义 鸟笼效应思维模型指的是人们在偶然获得一件原本不需要的物品后,会为了这件物品的配套或使用需求,进而继续添加更多与之相关但自己原本可能并不需要的东西,仿佛被这个“鸟笼”牵着走,最终陷入一种惯性消费或行为模式的现象。简单来说,就是人们在心理上会有一种自…