TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码
搜索到 2 篇与 的结果
2025-07-08

为什么C++数组下标从0开始:内存布局与历史原因深度解析

为什么C++数组下标从0开始:内存布局与历史原因深度解析
一、走进计算机的"物理视角"当我们用int arr[3] = {10,20,30};声明数组时,计算机在内存中构建的并非抽象概念,而是连续的物理存储单元。假设首地址为0x1000,内存布局呈现为:0x1000 [10] // arr[0] 0x1004 [20] // arr[1] 0x1008 [30] // arr[2]这个看似简单的设计,隐藏着两个关键特性: 1. 元素地址=基地址+偏移量:访问arr[i]时,CPU实际计算的是基地址 + i*sizeof(type) 2. 指针与数组的等价性:C++中arr[i]完全等价于*(arr + i)的指针操作零基索引使这个计算模型保持优雅:第一个元素的偏移量恰好为0,符合物理世界的直觉。如果从1开始,每次访问都需要执行*(arr + i - 1)的冗余计算。二、穿越到C语言的诞生时刻1969年,贝尔实验室的Dennis Ritchie在开发Unix系统时面临关键抉择。当时流行的语言如Fortran采用1-base索引,但Ritchie做出了颠覆性决定: BCPL语言的直接影响:作为C语言的前身,BCPL使用指针作为内存操...
2025年07月08日
1 阅读
0 评论
2025-07-07

指针算术:C++中的双刃剑与安全边界

指针算术:C++中的双刃剑与安全边界
一、指针算术的本质与先天限制指针算术(Pointer Arithmetic)是C++直接操作内存的核心能力,但它的自由性伴随着严格的约束条件: 仅适用于连续内存布局指针加减操作仅在数组或malloc分配的内存块中有效。对非连续结构(如链表节点)进行指针运算会导致未定义行为(UB)。例如: cpp int arr[5] = {1,2,3,4,5}; int* p = arr + 3; // 合法 std::list<int> lst = {1,2,3}; int* q = &(*lst.begin()) + 1; // 危险!链表非连续存储 类型敏感的步长计算指针加减的步长由基类型决定。int*移动4字节(32位系统),而double*移动8字节。这种隐性行为容易引发计算错误: cpp double data[10]; double* p = data; p += 5; // 实际移动5*8=40字节 不可跨对象边界C++标准明确规定:指针必须指向数组元素或尾后位置,跨越对象边界即属UB。即使物理内存连续,逻辑上仍属违规: cpp int a[5], b[5];...
2025年07月07日
2 阅读
0 评论