C语言:指针题型总结

本文系统总结C语言指针六大高频题型:二维数组逗号表达式初始化陷阱、数组指针与指针减法求元素个数、&数组名+1与数组名+1的语义差异、三级指针链式解引用与运算符优先级、指针数组自增行为、结构体指针强制转换后的步长规则。重点强调指针类型决定算术步长、同类型指针相减得元素数、逗号表达式值为最右操作数等核心机制,覆盖sizeof和&不退化、多级指针降级解引用等关键考点。

题型1:二维数组初始化 + 逗号表达式陷阱(最高频坑!)

代码:

int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];//*(a+0) 本来串的是第一行元素, a会退化成首元素地址
printf(“%d”, p[0]);

✅ 考点: () 里面是逗号运算符,不是行分组!逗号表达式只保留最右侧值
(0,1) → 结果是 1 ; (2,3) → 3 ; (4,5) → 5
内存填充: a[3][2] = {1,3,5,0,0,0} //剩余的填充0进去
输出: 1
❌ 误区:误以为 (0,1) 是一行两个元素(只有 {} 才是分组)
int a[3][2]={{0,1},{2,3},{4,5}};这个才是分组

题型2:数组指针 + 指针减法(求元素个数,不是字节差)

int a[5][5];
int (*p)[5]; // 数组指针:一步跨过一整行5个int
p = a;
printf(“%d, %d”, &p[4][2] - &a[4][2], &p[4][2] - &a[2][2]);

答案:0 10
每一行有5个元素,然后它跳过了两行,一共10个元素。
✅ 考点:

  1. 同类型指针相减,结果 = 中间相隔元素数量,不是字节
  2. int ()[5] 步长: 5sizeof(int) ; int* 步长:1个int

重点:小地址 - 大地址 → 负数

题型3:二维数组 + &aa+1 / *aa+1 区分(必考)

c

int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf(“%d,%d”, *(ptr1 - 1), *(ptr2 - 1));

✅ 考点拆分:

  • &aa :整个二维数组的地址,类型 int (*)[2][5] ; &aa+1 直接跳过整个二维数组
  • aa 是数组名, aa+1 :数组指针,跳过一行(5个int)
    输出: 10,5

题型4:三级指针 char*** 多级指针链式解引用(你那个ENTER/NEW题)

c

char* c[] = { “ENTER”,“NEW”,“POINT”,“FIRST” };
char** cp[] = { c + 3, c + 2, c + 1, c };
char*** cpp = cp;
printf(“%s\n”, ***cpp);
printf(“%s\n”, * ++cpp + 3);
printf(“%s\n”, *cpp[-2] + 3);
printf(“%s\n”, cpp[-1][-1] + 1);

先 画图:
c enter new point first
cp first point new enter
cpp =cp[0]=c[3] printf(“frist”);
*(++cpp)= cp[1] =c[2] point ->3 printf(“nt”);
cpp[-2] =cp[-1]=c[3] frist->printf(“st”);
cpp[-1][-1] = ((cpp-1)-1)+1=
(c+3-1)+1=oint
✅ 考点:

  1. 运算符优先级: ++/-- > * > +
  2. cpp[i] 等价 *(cpp+i) ;多层解引用逐层降一级指针
  3. char* + n :在字符串内部向后跳字母(步长1字节)
  4. char** + n :跳到下一个字符串首地址(步长是地址宽度)

核心口诀:解引用降一层;什么类型指针,+1就跳这个类型的大小

题型5:char*指针数组,指针自增

c

char* a[] = {“work”,“at”,“alibaba”};
char** pa = a;
pa++;
printf(“%s\n”, *pa);

✅ 考点: pa 是 char** ,pa++ 跳过一个 char* ,指向第二个字符串
输出: at

题型6:结构体指针 + 指针步长(强制转换指针,步长由类型决定)

c

struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}p;
// 题目给定:结构体大小20字节
p = (struct Test
)0x100000;
printf(“%p\n”, p + 0x1);
printf(“%p\n”, (unsigned long)p + 0x1);
printf(“%p\n”, (unsigned int*)p + 0x1);

✅ 考点(超级重要):

  • p + 1 :结构体指针,+1 跳整个结构体大小20字节,转16进制后是014
  • 转成普通整数 unsigned long 再加1:只+1个字节
  • unsigned int* 指针+1:跳4字节

本质:指针加法的步长,完全由指针本身的类型决定,和原始地址无关

配套通用考点笔记

  1. ✅ 数组名什么时候不退化: sizeof(数组名) 、 &数组名 ;其余全部退化成首元素指针
  2. ✅ 指针减法硬性规则:必须指向同一块连续内存,结果是元素个数,不是字节;小地址减大地址为负
  3. ✅ 逗号表达式: (a,b,c) ,顺序执行a→b→c,整个表达式的值 = 最右边c的值;只有 () 里逗号才是逗号运算符, {} 里面逗号只是分隔符!(本题最大坑)
  4. ✅ 多级指针分层:
  • char* → 存字符串首地址,+1跳1个字符
  • char** → 存 char* 的地址,+1跳一个字符串指针
  • char*** → 存 char** 的地址,+1跳一个char**
  1. ✅ [] 等价: p[i] == *(p+i) ,正负下标都合法(只要内存有效,考试随便考负数下标)

刷题顺序建议

  1. 先搞定【逗号表达式二维数组初始化】(最容易掉坑)
  2. 然后 &aa+1 vs aa+1 二维数组行指针题(aa为二维数组,实际为int()[],+1就直接跳到下一行了)
  3. 结构体指针步长(很多人分不清强制转换之后步长变了)
  4. 三级指针链式解引用(ENTER那道,运算符优先级地狱题)
  5. 指针减法+补码(负数地址打印)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值