【c语言】带你真正走进指针的世界——数组与指针的关系(二)

       什么叫写书的人不编程,编程的人不写书?

       书上面:一个自然数与另一个自然数(两个自然数都处于有效运算范围之内)得出的结果是一个比任何与之相加的自然数都要大的自然数。

       我:???

       老师:书上面的意思是想表达 : 1+1=2

————————————————下面是正文——————————————————       

一.指针数组

       定义:换言之就是说有一个数组,里面存的数据都是指针。

int arr[2] = {1,2};

       上面定义了一个类型为 (int) 类型的大小为 3 的数组,里面存了两个数据:1 和 2 。

int* arr[2] = {(int*)1,(int*)2};

       上面定义了一个类型为( int*) 类型的大小为 3 的数组,里面存了两个数据:1 和 2 。 注意:由于两个数据的类型是 (int) 类型的,所以是不能赋值给 (int*) 类型的数组的!!!需要进行强制类型转换,使两个数据的类型变为(int*)后才能赋值。在这时,数组里面存的数据就是地址而不是简单的数据了。

       下面来看看正常一点的使用方法:

char a = 'A';
char b = 'B';
char c = 'C';

char* pa = &a;
char* pb = &b;
char* pc = &c;

char* arr[4] = {pa,pb,pc};

printf("%d %d %d\n",arr[0],arr[1],arr[2]);

printf("%d %d %d\n",*arr[0],*arr[1],*arr[2]);

        上面的代码简单明了,就是 arr 这个指针数组里面存了三个指针,而这三个指针又分别保存了a、b、c的地址。编译的结果如下:

         汇编如下

         既然如此,那么我们可不可以这样写呢

char* arr[4] = {"A","B","C"};

printf("%d %d %d\n",arr[0],arr[1],arr[2]);

printf("%d %d %d\n",*arr[0],*arr[1],*arr[2]);

          编译结果如下

            汇编如下

      可以看到,这两种写法编译出来的结果是一样的,从汇编的结果中来看也是属于异曲同工之意,所以有好几种赋值方法~

小插曲:字符数组的打印

        当我给出下面这个数组的话

	char arr[5] = {'c','h','i','n','a'};
	printf("%s\n",arr);

        很多人会以为编译出来的结果是这样的

       其实只要打开你电脑上面的编译器跟着我编译一次,得出的结果是这样的

      这是为什么呢?别急,只要我在一个地方做个小小的修改

	char arr[6] = {'c','h','i','n','a'};
	printf("%s\n",arr);
	

       编译的结果立马就正常了

         我们先来看看汇编是怎么写的

         以下是打印出错误结果的汇编

        以下是打印出正确结果的汇编

   

         可以看出,打印正确结果的汇编比错误结果的汇编多了两句命令,这是因为:编译器在打印字符的时候,是需要有个终止命令符的,它会一直打印字符,直到看到终止命令符为止,而这个终止命令符,就是 “ \0 ” 。所以,在上面的两个结果中,第而个数组比第一个数组多了两条命令,这两条命令就是自动补上终止命令符 “xor  eax,eax ” 意为 “ eax 减去 eax ” 得出的结果是 “ 0 ”,而两个结果差别这么大的原因就是因为 第一个数组的长度比第二个数组的长度短,而刚好我们在初始化的时候把五个长度空间全部都用上了,所以没有地方在自动补全终止命令符,而第二个字符在初始化之后还有空间可以自动补全,所以第一个数组就会一直打印下去,直到看到终止命令符为止。

二.数组指针

      定义:数组指针是个指针,它是指向了一个数组的指针。

      具体怎么理解呢?请看下面我的表演

      首先我们来定义两个东西,一个是普通的数组,一个是数组指针

int arr[5] = {1,2,3,4,5}; //定义一个数组

int (*parr)[2] = &arr; //定义一个数组指针

      具体展开来可以是以下的展示

       以上是数组的定义

        以上是数组指针的定义

      数组名加一,指向下一个地址

       数组指针加一,指向下两个数据。

       所以,当出现以下代码时

	int arr[2] = {1,2};

	int (*px)[2];
	px = &arr;

	printf("%d\n",px);
	printf("%d\n",*px);

       你会发现,编译出来的结果是一样的

      这就是因为

      赋值号左右两边的类型是需要一样才可以赋值的(具体可以查看我的另外一篇文章:https://blog.csdn.net/qq_41884002/article/details/84258830),而 “ px ” 的类型是 int (*) [2] 类型,“ arr ” 类型是  int [2] 类型,所以如果想要类型相等,就加上一个取址运算符(作用是加星号,具体可以查看我的另外一篇文章,连接子在上面),使得arr 类型变成 int (*) [2] 类型,然后就可以赋值。

      那么, ” px “ 存的就是 int (*)[2] 类型的数据,也就是 ” arr “ 数组的首地址,而 ” *px “ (* 的作用的去掉星号,具体还是可以看我另外一篇文章~) 存的是 int* 类型的数据,还是 ” arr “ 的首地址,所以两个输出的结果是一样的。

     所以,如果想通过数组指针输出数组的值的话,可以这样来写

	int arr[2] = {1,2};

	int (*px)[2];
	px = &arr;

	printf("%d\n",*(*(px)));

      得出的结果是

猜你喜欢

转载自blog.csdn.net/qq_41884002/article/details/84873732
今日推荐