Loading

指针数组和数组指针的区别

一、问题引入

在使用C语言编程时,一旦涉及到指针数组和数组指针就会陷入困惑。

  • 如何区分指针数组和数组指针的定义形式

  • 在某个场景下,应该使用指针数组,还是使用数组指针

  • 指针数组和数组指针如何作为参数传递

二、解决过程

2-1 指针数组

指针数组是一个数组,每个数组元素存放一个指针变量。

例如: char *p[2]; 中的 p 就是一个指针数组,p拥有两个元素,可以存放两个变量的地址。

💡 注意:[ ] 运算符的优先级高于 * 运算符

代码举例-01:

#include <stdio.h>

int main(void)
{
    char str_01[] = {"《C程序设计》"}, str_02[] = {"《算法与数据结构》"};	
    char *p[2]; // p 是一个拥有两个元素的指针数组

    p[0] = str_01;
    p[1] = str_02;
    for(int i = 0; i < 2; i++)
    {
        printf("第%d本书:%s\n", i+1, *(p+i)); 
    }
    return 0;
}

重点语句理解:printf("第%d本书:%s\n", i+1, *(p+i)); ,如何介绍 *(p+i) 的解引用?
(p+i) 表示数组的第i元素,*(p+i) 表示解引用数组的第i元素的地址。但是让我困惑的一点是 (p+0) 不就是 str_01数组的地址吗,为什么还要解引用?

首先应该理解什么是指针,才能理解指针数组。指针是一种特殊的变量,它里面存放的是地址,不是我们普通概念的值,它也有自己的地址值,它的取值是别的变量的地址值。
说回 char *p[2] char类型的指针数组,包含两个指针且指针的地址是连续的(假设 0X000000040X00000008)。那就说明第一个指针(0X00000004)存放 str_01(0X0000FF00) 的地址,第二个指针(0X00000008)存放 str_01(0X0000EE00) 的地址。
(p+0) 表示第一个指针,我们要的不是第一个指针,而是第一个指针的值(即str_01的地址),因此还要对第一个指针进行取值(即 *(p+0))

借助一下代码,理解指针的意义

#include <stdio.h>
int main(int argc, const char *argv[])
{
	char str_01[] = { "《C程序设计》" }, str_02[] = { "《算法与数据结构》" };
	char *p[2]; // p 是一个拥有两个元素的指针数组
	printf("str_01的地址:%p\n", str_01);
	printf("str_02的地址:%p\n", str_02);
	printf("\n");

	p[0] = str_01;
	p[1] = str_02;
	
	for (int i = 0; i < 2; i++)
	{
		printf("(p+i)的地址:%p\n", i, (p + i));
		printf("*(p+i)的地址:%p\n", i, *(p + i));
		printf("第%d本书:%s\n", i + 1, *(p + i));
		printf("\n");
	}
	return 0;
}

代码举例-02:

#include <stdio.h>

int main(void)
{
    char *p[2] = 
    {
        "《C程序设计》",
        "《算法与数据结构》"
    };
    for(int i = 0; i < 2; i++)
    {
        printf("第%d本书:%s\n",i+1, *(p+i)); //p+i表示数组第i个元素的地址,*(p+i)表示第i个元素的值
    }
    return 0;
}

代码举例-01 和 代码举例-02 结果是等价

程序运行结果:

2-2 数组指针

数组指针是一个指针,指向拥有n(n>1)个元素的数组,所指向的数组的元素一般是固定的。

例如:int (*p)[5]; 中的 p 就是一个数组指针,指针指向拥有5个元素的数组

代码举例:

#include <stdio.h>
int main()
{
	int temp[5] = {1, 2, 3, 4, 5};
	int(*p)[5] = &temp;
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", *(*p + i));
	}
	printf("\n");
	return 0;
}

💡 数组指针p指向拥有5个元素的数组的首地址,不能将超过5个元素的数组的地址赋值给数组指针p

运行结果:

三、指针数组作为参数

若想将指针数组作为参数传入函数,应该怎样传递呢?

#include <stdio.h>

void print_book(char **ptr, int num)  // 形参是一个二级指针 即指向指针的指针
{
	for (int i = 0; i < num; i++)
	{
                printf("(ptr+%d)的地址:%p\n", i, ptr+i);
		printf("*(ptr+%d)的地址:%p\n", i, *(ptr + i));
		printf("第%d本书:%s\n", i + 1, *(ptr + i));
	}
}

int main(int argc, const char *argv[])
{
	
	char str_01[] = { "《C程序设计》" }, str_02[] = { "《算法与数据结构》" };
	char *p[2]; // p 是一个拥有两个元素的指针数组
	p[0] = str_01;
	p[1] = str_02;
        printf("p的地址:%p\n\n", p);
	print_book(p, 2);  // 实参是指针数组的首地址 或者说是指针数组第一个元素的地址
        //print_book(&p[0], 2); // p 和 &p[0] 是等价的
	return 0;
}

四、数组指针作为参数

若想将数组指针作为参数传入函数,该如何定义形参呢?

#include <stdio.h>

int print_number(int (*p)[5])
{
        int i;
        for (i = 0; i < 5; i++)
        {
                printf("%d ", *(*p + i));
        }
        printf("\n\n");
        return 0;
}

int print_book(char (*p)[50])
{
        int i;
        for(i = 0; i < 2; i++)
        {
                printf("%p %p %s\n", p+i, *(p+i), *(p+i));
        }
        printf("\n");
        return 0;
}

int main(void)
{
        int temp[5] = {1, 2, 3, 4, 5};
        int(*p)[5] = &temp;  // 将数组temp的地址赋值给数组指针p
        print_number(p);

        char book[2][50] = {"C程序设计", "C++程序设计"};
        printf("book[0]'s address:%p\nbook[1]'s address:%p\n", book[0], book[1]);
        char (*p_book)[50] = book; // 将数组第一个元素的首地址赋值给数组指针p_book
        printf("(*p_book)[50]'s address:%p\n", p_book);
        print_book(p_book);
        return 0;
}

❓ 注意:book[0]、(*p_book)[50]、(p+0)和*(p+0)的地址相同
如何理解:printf("%p %p %s\n", p+i, *(p+i), *(p+i)); 中 p+i, *(p+i)地址相同的问题?

分析过程:首先,0x7ffee0b6a3e00x7ffee0b6a412 的差值:50,这验证了 char (*p)[50] 数组指针的跨度单位是 50。
其次,p+i 指向一维数组的地址,*(p+i) 指向一维数组第一个元素的地址。对于一维数组而言,数组的首地址和第一个元素的地址值是相同,这就说明了 p+i, *(p+i)地址相同的问题

五、反思总结

重点理解

  • 指针数组和数组指针的定义和形式
  • 指针数组其属性是一个地址连续的数组。数组元素是指针,指针是指向地址的。
  • 数组指针,数组是对指针的约束条件。未明确说明数组长度,不能将其地址赋值给数组指针

2023-08-23 新增内容:

四、数组指针作为参数 中,char book[2][50] = {"C程序设计", "C++程序设计"};sizeof(book) 是多少?
int print_book(char (*p)[50])sizeof(p) 是多少?

答案:sizeof(book)=100、sizeof(p)=8 (在windows10-x64实现)

六、参考引用

二维数组和二级指针(真的没什么关系)

posted @ 2023-01-31 10:14  eiSouthBoy  阅读(1070)  评论(0)    收藏  举报