ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

嵌入式开发学习日志(指针与数组及传参) day12 持续更新中

嵌入式开发学习日志(指针与数组及传参) day12 持续更新中

一、指针与一维字符型数组的关系

1. 数组名的本质

  • 一维字符数组char str[] = {"hello"};中,str是数组名,它代表首元素地址,即&str[0],类型为char *
  • 数组名是一个地址常量,不可被赋值修改(如str = ...非法)。

2. 指针算术运算

  • str + 1指向第二个元素str[1],地址偏移量为sizeof(char)字节(通常为1字节)。
  • str + n指向第n+1个元素,等价于&str[n]
  • 解引用*(str + n)等价于str[n]

3. 内存布局示意

地址: 0x2000 0x2001 0x2002 0x2003 0x2004 0x2005 内容: 'h' 'e' 'l' 'l' 'o' '\0' 指针: str str+1 str+2 str+3 str+4 str+5

注意:字符串以\0结尾,是C语言字符串处理的终止标志。

4. 函数参数传递

  • 函数形参char str[]char *str等价,均接收数组首地址。
  • 示例:int mystrlen(char str[])int mystrlen(char *str)功能完全相同。

二、数组指针

1. 定义与本质

  • 数组指针:本质是指针,指向整个数组
  • 语法:int (*p)[5];—— 声明一个指针p,它指向一个包含5个int元素的数组。
  • 该指针变量本身占8字节(64位系统),但其指向的内存块大小为5 * sizeof(int)

2. 与普通指针的区别

  • int a[5] = {1,2,3,4,5};
    • a&a[0]:类型为int *,指向首元素。
    • &a:类型为int (*)[5],指向整个数组。
  • a + 1:偏移sizeof(int)字节 → 指向a[1]
  • &a + 1:偏移sizeof(a)字节 → 指向数组末尾之后的位置(即跳过整个数组)。

3. 内存布局示意

地址: 0x2000 0x2004 0x2008 0x200C 0x2010 0x2014 内容: 1 2 3 4 5 (越界) 指针: a a+1 a+2 a+3 a+4 &a+1 ↑ &a (指向整个数组)

4. 特别注意

  • sizeof(a)返回整个数组大小(如5 * 4 = 20字节)。
  • &a不能当作int *使用,其类型是int (*)[5],用于指向数组整体。

三、指针与二维数组

1. 二维数组的本质

  • 二维数组int a[2][3] = {1,2,3,4,5,6};在内存中是连续存储的,按行优先排列。
  • 数组名a代表首行地址,即&a[0],类型为int (*)[3](指向含3个int的一维数组)。
  • a[0]是第一行的数组名,类型为int *,指向a[0][0]
  • a[1]是第二行的数组名,类型为int *,指向a[1][0]

2. 指针运算与访问

  • a + 1→ 指向第二行,即&a[1],偏移量为3 * sizeof(int)
  • *(a + m) + n→ 等价于&a[m][n]
  • *(*(a + m) + n)→ 等价于a[m][n]

3. 内存布局示意

地址: 0x2000 0x2004 0x2008 0x200C 0x2010 0x2014 内容: 1 2 3 4 5 6 行指针: a[0] ← a[0][0]~a[0][2] a[1] ← a[1][0]~a[1][2] 整体指针: a → &a[0], a+1 → &a[1]

4. 作为函数参数传递

  • 二维数组作函数参数时,必须指定列数,行数可省略。

  • 正确写法:

    void print_2D_array(int a[][3], int hang); // 列数必须指定 void print_2D_array(int (*pa)[3], int hang); // 数组指针形式
  • 调用:print_2D_array(a, 2);

  • 字符型二维数组同理:

    char str[3][100] = {"hello", "world", "thanks"}; void print_str_array(char str[][100], int hang); void print_str_array(char (*pstr)[100], int hang);

总结对比表

概念类型含义示例
一维数组名T *首元素地址str&str[0]
数组指针T (*)[N]指向整个数组&aint (*)[5]
二维数组名T (*)[N]首行地址a&a[0]
二维数组行名T *某行首元素地址a[0]&a[0][0]
函数参数传递T arr[][N]T (*p)[N]必须指定列数void f(int a[][3])
返回列表