题型1:二维数组初始化 + 逗号表达式陷阱(最高频坑!)
代码:
int a32 = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a0;//*(a+0) 本来串的是第一行元素, a会退化成首元素地址
printf("%d", p0);
✅ 考点: () 里面是逗号运算符,不是行分组!逗号表达式只保留最右侧值
(0,1) → 结果是 1 ; (2,3) → 3 ; (4,5) → 5
内存填充: a32 = {1,3,5,0,0,0} //剩余的填充0进去
输出: 1
❌ 误区:误以为 (0,1) 是一行两个元素(只有 {} 才是分组)
int a32={{0,1},{2,3},{4,5}};这个才是分组
题型2:数组指针 + 指针减法(求元素个数,不是字节差)
int a55;
int (*p)5; // 数组指针:一步跨过一整行5个int
p = a;
printf("%d, %d", &p42 - &a42, &p42 - &a22);
答案:0 10
每一行有5个元素,然后它跳过了两行,一共10个元素。
✅ 考点:
- 同类型指针相减,结果 = 中间相隔元素数量,不是字节
- int ()5 步长: 5sizeof(int) ; int* 步长:1个int
重点:小地址 - 大地址 → 负数
题型3:二维数组 + &aa+1 / *aa+1 区分(必考)
c
int aa25 = {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 (*)25 ; &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 =cp0=c3 printf("frist");
*(++cpp)= cp1 =c2 point ->3 printf("nt");
cpp-2 =cp-1=c3 frist->printf("st");
cpp-1-1 = ((cpp-1)-1)+1= (c+3-1)+1=oint
✅ 考点:
- 运算符优先级: ++/-- > * > +
- cppi 等价 *(cpp+i) ;多层解引用逐层降一级指针
- char* + n :在字符串内部向后跳字母(步长1字节)
- 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 cha2;
short sBa4;
}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字节
本质:指针加法的步长,完全由指针本身的类型决定,和原始地址无关
配套通用考点笔记
- ✅ 数组名什么时候不退化: sizeof(数组名) 、 &数组名 ;其余全部退化成首元素指针
- ✅ 指针减法硬性规则:必须指向同一块连续内存,结果是元素个数,不是字节;小地址减大地址为负
- ✅ 逗号表达式: (a,b,c) ,顺序执行a→b→c,整个表达式的值 = 最右边c的值;只有 () 里逗号才是逗号运算符, {} 里面逗号只是分隔符!(本题最大坑)
- ✅ 多级指针分层:
- char* → 存字符串首地址,+1跳1个字符
- char** → 存 char* 的地址,+1跳一个字符串指针
- char*** → 存 char** 的地址,+1跳一个char**
- ✅ \[\] 等价: pi == *(p+i) ,正负下标都合法(只要内存有效,考试随便考负数下标)
刷题顺序建议
- 先搞定【逗号表达式二维数组初始化】(最容易掉坑)
- 然后 &aa+1 vs aa+1 二维数组行指针题(aa为二维数组,实际为int()\[\],+1就直接跳到下一行了)
- 结构体指针步长(很多人分不清强制转换之后步长变了)
- 三级指针链式解引用(ENTER那道,运算符优先级地狱题)
- 指针减法+补码(负数地址打印)