二重指针、二维数组、二维数组和指针的运算

(1)二重指针

(1)本质上来说,二重指针和一重指针的本质都是指针变量,指针变量的本质就是变量。
(2)一重指针变量和二重指针变量本身都占8字节内存空间(64位)

二重指针的简单应用:

	int a = 10;
	int *p = NULL;
	int **p1 = NULL;
	
	p = &a;
	p1 = &p;
	
	printf("*p=%d\n",*p);
	printf("**p1 = %d\n",**p1);

二重指针和指针数组结合

#include <stdio.h>

int main()
{
    
    
int *a[10];
int **p1 = NULL;
p1 = a;
//a是数组名,相当于首元素首地址,首元素是指针,a也就相当于地址的地址。和int** 匹配

}

二重指针充当函数形参

#include<stdio.h>

void func(int **p)
{
    
    
	*p = (int *)0x12345678;
}

int main(void)
{
    
    
int a = 4;
int *p = &a;				// p指向a
printf("p = %p.\n", p);		// p打印出来就是a的内存地址
func(&p);					// 在func内部将p指向了别的地方
printf("p = %p.\n", p);		// p已经不指向a了,所以打印出来不是a的地址
*p = 23;					// 因为此时p指向0x12345678,但是这个地址是不允许访问的,因此会段错误。

(2)二维数组

(1)从内存角度来看,一维数组和二维数组没有本质差别。
(2)二维数组int a[2][5]和一维数组int b[10]其实没有任何本质差别。我们可以把两者的同一单元的对应关系写下来。

a[0][0]	 a[0][1]   a[0][4]	 a[1][0]	a[1][1]	  a[1][4]	
b[0]	 b[1]	   b[4]	     b[5]	    b[6]	  b[9]

(3)第一维和第二维
3.1 int a[2][3]中的2是第一维,3是第二维。
3.2 结合内存映像来理解二维数组的第一维和第二维的意义。首先第一维是最外面一层的数组,所以int a[2][3]这个数组有2个元素;其中每一个元素又是一个含有3个元素的一维数组(这个数组就是第二维)。
在这里插入图片描述
(4)二维数组的定义:

int a[2][5] = {
    
    {
    
    1, 2, 3, 4, 5}, {
    
    6, 7, 8, 9, 10}};
//int a[2][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

二维数组下标访问

int a[2][5] = {
    
    {
    
    1, 2, 3, 4, 5}, {
    
    6, 7, 8, 9, 10}};
//int a[2][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	
int *p = a;		// 类型不匹配
//应该是 int (*p)[5] = a;//a相当于&a[0]	
printf("a[1][3] = %d.\n", a[1][3]);    // 9
printf("a[1][3] = %d.\n", *(*(a+1)+3)); // 9

史上最详细分析:
(1)a等同于&a[0],&a[0]是在第一维中的首元素首地址,a[0]表示第一维中的首元素
(2)a+1相当于&a[1],是第一维的数组中的第二个数组元素的首地址
(3)a,表示第一维数组中的首元素,该元素也是第二维的数组的数组名,就是第二维的一维数组的首元素首地址。
(4)
(a+1),表示第一维数组中的第二个元素,该元素也是第二维的数组的数组名,就是第二维的一维数组的首元素首地址。
(5)(a+1)+3,表示,表示第一维数组中的第二个元素,该元素也是第二维的数组的数组名,+3后表示从第二维的一维数组的首元素首地址偏移了3位之后的地址
(6)
(*(a+1)+3),对(5)里面的地址进行解引用,得到值 9;

二维数组的运算和指针(a和a[0])

(1)数组中各个符号的意义

先定义个二维数组

int a[2][5] = {
   
   {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};

a[0]= &a[0][0] ,二维数组的第一维的第一个元素,相当于是第二维的第一个整体数组的数组名。数组名又表示数组首元素首地址,因此a[0]等同于&a[0][0]

int a[2][5] = {
    
    {
    
    1, 2, 3, 4, 5}, {
    
    6, 7, 8, 9, 10}};
int *p4 = a[0];	//不报错,int * 类型和第二维的一维数组是匹配的。
int *p5 = &a[0][0];	//和上面一样

(2)指针指向二维数组的第一维


//int *p4 = &a[0];		// 不可以

int *p4 = a[0];			// a[0]表示二维数组的第一维的第一个元素,相当于是第二维的整体数组的数组名。数组名又表示数组首元素首地址,因此a[0]等同于&a[0][0];
	
int *p5 = &a[0][0];	
printf("a[0][4] = %d.\n", *(p4+4));//访问a[0][4]
int *p6 = a[1];
printf("a[1][1] = %d.\n", *(p6+1));//访问a[1][1]

指针指向二维数组的数组名
(1)a是二维数组的数组名,作为右值表示二维数组第一维的数组的首元素首地址,等同于&a[0],所以想要设置一个指针指向a,必须是数组指针p

p指向第一维的数组

	
int (*p3)[5];// 数组指针,指针指向一个数组,数组有5个int类型元素,p3+1就直接跑到第一维的下一个数组去
p3 = a;// a是二维数组的数组名,作为右值表示二维数组第一维的数组的首元素首地址,等同于&a[0]
p3 = &a[0];//同上
	
printf("a[0][3] = %d.\n", *(*(p3+0)+3));
printf("a[1][4] = %d.\n", *(*(p3+1)+4));

总结:

小了,小了,a[0]比a的格局小了。

猜你喜欢

转载自blog.csdn.net/shun1296/article/details/114767726