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

2023-12-12 10:08

本文主要是介绍二重指针、二维数组、二维数组和指针的运算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(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的格局小了。

这篇关于二重指针、二维数组、二维数组和指针的运算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/484216

相关文章

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE