C语言二维数组地址计算与经典面试题详解(附答案)-持续更新
2026/8/9 9:01:17 网站建设 项目流程

一、二维数组地址计算公式

计算二维数组地址,核心只有三步:确定基址 → 数清前面元素个数 → 乘以元素字节数

绝大多数语言(C/C++/Java)采用行优先存储(先存满第一行,再存第二行),记住这一个公式就够了:

Addr = 基址 + (i × 总列数 + j) × 单个元素大小
  • 下标从 0 起(如A[i][j]):直接套用公式。
  • 前面的元素个数 =i行完整的元素 + 第i行中j前面的元素。

举个极简例子int A[3][4](3行4列),基址=1000,int占4字节,求A[1][2]

前面元素数 = 1×4 + 2 = 6 个,地址 = 1000 + 6×4 =1024


二、数组名的三种含义

  1. sizeof(数组名)—— 数组名表示整个数组,计算整个数组的大小。
  2. &数组名—— 数组名表示整个数组,取出整个数组的地址。
  3. 其他所有情况 —— 数组名表示首元素的地址

三、经典面试题实战

1. 一维数组a&a的区别

#include<stdio.h>intmain(){inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));return0;}

输出结果2,5

解析

  • a:数组名,转为int*a+1偏移1个int*(a+1) = a[1] = 2
  • &a:整个数组的地址,类型为int(*)[5]&a+1跳过整个数组(5个int),指向数组尾后。
  • ptr强转为int*ptr-1回退1个int,指向a[4],取值为5

核心考点:地址值可能相同,但指针类型不同,步长完全不同


2. 指针步长与强制类型转换

// x86 32位,假设struct Test大小20字节structTest{intNum;char*pcName;shortsDate;charcha[2];shortsBa[4];}*p=(structTest*)0x100000;intmain(){printf("%p\n",p+0x1);printf("%p\n",(unsignedlong)p+0x1);printf("%p\n",(unsignedint*)p+0x1);return0;}

输出结果

0x100014 0x100001 0x100004

解析

  1. p+0x1struct Test*指针,+1 偏移sizeof(struct Test)=20(0x14)0x100000+20 = 0x100014
  2. (unsigned long)p+0x1:转为普通整型,纯数字加1 →0x100000+1 = 0x100001
  3. (unsigned int*)p+0x1int*指针,+1 偏移4字节 →0x100000+4 = 0x100004

考点:指针加法偏移量 = 个数 ×sizeof(指向类型);整数强转后不能再当指针解引用。


3. 逗号运算符 + 二维数组初始化

#include<stdio.h>intmain(){inta[3][2]={(0,1),(2,3),(4,5)};int*p;p=a[0];printf("%d",p[0]);return0;}

输出结果1

解析

  • (0,1)是逗号表达式,取最右侧值,所以(0,1)=1(2,3)=3(4,5)=5
  • 数组实际初始化:int a[3][2] = {1, 3, 5},剩余元素自动置0。
  • p[0]等价于a[0][0],输出1

陷阱()不是{},圆括号触发逗号运算符。正确二维初始化应写成{{0,1},{2,3},{4,5}}


4. 数组指针与指针相减

#include<stdio.h>intmain(){inta[5][5];int(*p)[4];p=a;printf("%p,%d\n",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);return0;}

输出结果FFFFFFFC,-4(32位环境)

解析

  1. int (*p)[4]:数组指针,指向大小为4的int数组;p+1偏移4*sizeof(int)=16字节。
  2. p=aint[5][5]的首行地址赋给p,但p的步长是int[4]
  3. p[4][2]等价*(*(p+4)+2)
    • p+4偏移4个int[4]→ 偏移了4×4 = 16个int。
    • a[4][2]是数组a第4行第2列,距起始4×5+2 = 22个int。
    • &p[4][2]距起始16+2 = 18个int。
  4. 指针相减得到元素个数差:18 - 22 = -4
  5. %p-4按无符号地址打印,输出FFFFFFFC%d正常输出-4

考点:数组指针步长由[]内数字决定;同类型指针相减得到的是元素个数,不是字节数。


5.&aa+1aa+1的区别(二维数组)

#include<stdio.h>intmain(){intaa[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));return0;}

输出结果10,5

解析

  • &aa:整个二维数组的地址;&aa+1跳过整个数组(10个int),指向数组末尾之后。
  • ptr1 = (int*)(&aa+1)ptr1-1回退1个int,指向最后一个元素10
  • aa:数组名,aa+1指向第二行,等价&aa[1]*(aa+1)得到第二行首元素地址(元素6的地址)。
  • ptr2指向6,ptr2-1回退到上一行末尾,取值5

考点&数组名+1跳过整个数组数组名+1跳过一行


6. 字符指针数组与二级指针

#include<stdio.h>intmain(){char*a[]={"work","at","alibaba"};char**pa=a;pa++;printf("%s\n",*pa);return0;}

输出结果at

解析

  • char* a[]:字符指针数组,每个元素指向一个字符串常量。
  • pa初始指向a[0](即指向"work"的指针),pa++后移一个char*大小,指向a[1]
  • *pa得到a[1],即"at"的首地址,打印at

考点char* a[]是指针数组;二级指针加减步长是指针类型的大小。


7. 多级指针、指针数组与运算符优先级(压轴题)

#include<stdio.h>intmain(){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);return0;}

输出结果

POINT ER ST EW

逐步解析

  • 初始状态:
    • c[]={"ENTER", "NEW", "POINT", "FIRST"}
    • cp[]={&c[3], &c[2], &c[1], &c[0]}(即cp[0]指向"FIRST"的指针,以此类推)
    • cpp指向cp[0]
  1. **++cpp

    • ++cppcpp指向cp[1]
    • 第一次解引用得到c+2
    • 第二次解引用得到c[2],即"POINT"。 →POINT
  2. *-- * ++cpp + 3

    • ++cppcpp指向cp[2]
    • *cpp得到c+1
    • --(*cpp)cp[2]的值从c+1改为c(指向"ENTER");
    • 解引用得到"ENTER"首地址,+3偏移三个字符,指向E后面的R,输出ER。 →ER
  3. *cpp[-2] + 3

    • 此时cpp仍指向cp[2]
    • cpp[-2]等价*(cpp-2),得到cp[0],即c+3(指向"FIRST");
    • 解引用并+3,从F跳过三个字符得到S,输出ST。 →ST
  4. cpp[-1][-1] + 1

    • cpp[-1]得到cp[1],其值仍为c+2(未被修改);
    • (c+2)[-1]等价*(c+2-1) = c[1],即"NEW"
    • +1偏移一个字符,得到"EW"。 →EW

考点总结

  • ++/--优先级高于*[]等价于指针加减。
  • cpp[-2]表示*(cpp-2),负下标完全合法。
  • *-- * ++cpp--修改了指针数组里的值,会影响后续所有用到该位置的计算。

四、总结

二维数组地址计算看似简单,但一旦结合数组名、数组指针、指针步长、强制类型转换以及运算符优先级,就会衍生出各种让人头疼的面试题。核心还是要牢记三点:

  1. 地址公式基址 + (i×列数 + j)×元素大小
  2. 指针步长:由指针类型严格决定(&数组名+1跳整个数组,数组名+1跳一行)
  3. 表达式优先级:善用括号,理解*++[]的运算顺序。

希望这篇整理能帮你彻底拿下 C 语言中的二维数组与指针难题!

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

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

立即咨询