冯站长之家格尔木市公司网站建设
2026/4/15 11:47:08 网站建设 项目流程
冯站长之家,格尔木市公司网站建设,品牌网站制作建设,设计工作室是做什么的一、指针和数组名可互换的场景#xff08;核心#xff1a;数组名被隐式转换为指针#xff09;在绝大多数表达式场景中#xff0c;数组名会被编译器隐式转换为指向数组第一个元素的指针#xff08;这个转换也叫“数组退化为指针”#xff09;#xff0c;此时二者的用法完…一、指针和数组名可互换的场景核心数组名被隐式转换为指针在绝大多数表达式场景中数组名会被编译器隐式转换为指向数组第一个元素的指针这个转换也叫“数组退化为指针”此时二者的用法完全等价。1. 访问数组元素[]下标访问数组名用下标访问本质是*(数组名 偏移量)指针也支持同样的语法二者完全互换。#include stdio.h int main() { int arr[5] {1,2,3,4,5}; int *p arr; // 数组名arr隐式转为指向arr[0]的指针 // 以下4种写法完全等价输出均为3 printf(%d\n, arr[2]); // 数组名下标 printf(%d\n, *(arr2)); // 数组名转指针指针运算 printf(%d\n, p[2]); // 指针下标 printf(%d\n, *(p2)); // 指针指针运算 return 0; }2. 函数参数传递当数组作为函数参数时编译器会自动将其转换为指向第一个元素的指针即使写int arr[]实际也是int *arr此时形参的指针和实参的数组名完全互换。// 形参写int arr[] 或 int *arr 效果完全一样 void print_arr(int arr[], int len) { for(int i0; ilen; i) { printf(%d , *(arri)); // 等价于arr[i] } } int main() { int arr[5] {1,2,3,4,5}; int *p arr; print_arr(arr, 5); // 传数组名 print_arr(p, 5); // 传指针效果完全相同 return 0; }3. 取地址后访问数组名取地址arr是指向整个数组的指针指针取地址p是指向指针变量的指针但如果仅用于访问元素仍可互换需注意类型匹配。int arr[5] {1,2,3,4,5}; int *p arr; // 访问arr[1]以下写法等价 printf(%d\n, (*arr)[1]); // arr是数组指针解引用后回到数组名 printf(%d\n, (*p)[1]); // p是指针的指针解引用后回到指针p二、指针和数组名不可互换的场景核心数组名是“常量”指针是“变量”数组名的本质是数组首元素地址的常量不能被修改而指针是存放地址的变量可自由修改这一本质区别导致以下场景绝对不能混用。1. 试图修改数组名赋值操作数组名是常量不能被赋值指针是变量可随意赋值指向不同地址。int arr[5] {1,2,3,4,5}; int *p arr; p; // 合法指针变量可以自增指向arr[1] // arr; // 非法编译报错数组名是常量不能修改lvalue required p arr[2]; // 合法指针指向arr[2] // arr arr[2]; // 非法数组名不能被赋值2. 使用sizeof运算符sizeof(数组名)计算的是整个数组的字节大小sizeof(指针)计算的是指针变量本身的字节大小与平台有关32位系统4字节64位8字节二者结果完全不同。int arr[5] {1,2,3,4,5}; int *p arr; // 关键区别 printf(%zu\n, sizeof(arr)); // 输出205个int每个4字节5*420 printf(%zu\n, sizeof(p)); // 输出864位系统或432位系统 // 即使指针指向整个数组结果仍不同 int (*arr_ptr)[5] arr; // 指向整个数组的指针 printf(%zu\n, sizeof(arr_ptr)); // 还是8/4不是203. 取地址运算的类型和偏移arr是指向整个数组的指针类型为int (*)[5]p是指向指针变量的指针类型为int **二者的偏移规则完全不同混用会导致地址错误。int arr[5] {1,2,3,4,5}; int *p arr; // arr是数组指针int (*)[5]1偏移整个数组的大小20字节 printf(%p\n, arr); // 假设输出0x7ffeefbff560 printf(%p\n, arr 1); // 输出0x7ffeefbff5740x560 20 0x574 // p是指针的指针int **1偏移指针变量的大小8字节 printf(%p\n, p); // 假设输出0x7ffeefbff558 printf(%p\n, p 1); // 输出0x7ffeefbff5600x558 8 0x560 // 若强行混用会访问错误地址 int (*ap)[5] p; // 类型不匹配编译警告运行时访问错误4. 字符串常量与字符数组特殊场景字符数组名是可修改的数组元素可改而指向字符串常量的指针是只读的混用会导致运行时错误。// 字符数组内存在栈上可修改 char str_arr[] hello; str_arr[0] H; // 合法输出Hello // 字符串指针指向只读数据区.rodata不可修改 char *str_ptr hello; // str_ptr[0] H; // 非法编译可能通过但运行时崩溃段错误三、底层原理总结特性数组名指针本质数组首元素地址的常量存放地址的变量是否可修改不可如、赋值可如、指向新地址sizeof运算整个数组的字节大小指针变量本身的字节大小取地址类型指向整个数组的指针指向指针变量的指针总结可互换场景仅当数组名被隐式转换为指针时如下标访问、函数参数传递指针和数组名的用法完全等价不可互换场景涉及修改操作如、赋值、sizeof运算、取地址后的偏移、字符串常量修改时二者本质不同绝对不能混用核心记忆点数组名是“常量指针”地址不可改指针是“变量指针”地址可改这是二者所有区别的根源。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询