解析数组与指针澳门新葡亰3522网址:

By admin in 澳门新葡亰3522网址 on 2019年9月28日

指针和数组为什么这么纠缠不清

首先说一点,指针的使用等同于数组的情况远远多于他们不同的情况,因此,在初学时,为了容易理解,很多人都说 “指针=数组”。 但是,这却是错误的!

来个例子吧:

// file1.c 定义一个数组arrayint array[100];
以上是在文件1中的定义

// file2.c 声明file1.c中的arrayextern int* array
以上是在文件2中的声明

上面的例子对不对呢? 大家可以自己测试下,会很神奇的发现:
咔,怎么编译出错啦! 为什么呢?

数组的使用

任何时候,都可以变成指针表达式

澳门新葡亰3522网址 1

我们归纳下:

1、 “表达式中的数组名” 就是指针,
及你可以使用a[i];
*; p=a,
p+i,*p;等形式表达同样的意思。

2、C语言将数组下标作为指针的偏移量

3、作为函数形参的数组名,等同于指针,即:

my_func(int* p);my_func(int p[]);my_func(int p[200]); 

都是一个意思,编译器都把它翻译成指针。


继续深入声明和定义

在辨析数组和指针前,首先要说下声明和定义的区别,之前博文“为何不精通C? 03
深入剖析声明” 中的末尾已经提过这一点了。这里重新说下:

C语言中,对象有且仅有一个定义,而声明却可以有多个extern 声明。

定义:只能出现在一个地方,确定同时分配内存,它是特殊的声明

声明:只是描述其他地方创建对象的属性。有extern前缀,作用于变量

对于声明,就像断言一样,说是什么就是什么,不容许有妥协的余地,因为在声明的同时,也规定了指针/数组的移动方式及长度。

So,
对于上面的例子,我们可以知道,file2.c中,array被声明成一个int指针。但是,file1.c
中的定义却是数组。 他们不兼容! 为什么不兼容呢?

通过指针和数组访问数据的方式不同

这里先补充一个知识点,sizeof 这个运算符,它返回的是x在内存中的字节数。

  1 #include "stdio.h"  0 main ()  1 {  2   int array[20];  3   printf("类型\t字节数\t指针字节数\n");  4   printf("%s\t%d\t%d\n","char",sizeof(char), sizeof(char*));  5   printf("%s\t%d\t%d\n","short",sizeof(short), sizeof(short*));  6   printf("%s\t%d\t%d\n","int",sizeof(int), sizeof(int*));  7   printf("%s\t%d\t%d\n","long",sizeof(long), sizeof(long*));  8   printf("%s\t%d\t%d\n","float",sizeof(float), sizeof(float*));  9   printf("%s\t%d\t%d\n","double",sizeof(double), sizeof(double*)); 10   printf("%s\t%d\t%d\n","array",sizeof, sizeof(&array[0])); 11   return 0; 12 }

澳门新葡亰3522网址 2

这里,我们可以归纳出,所有的指针长度都是固定的,
都是4字节(因为我的电脑是32位=4*8bit。同理,在64位电脑这里显示8)。
我们认真观察下第10行,sizeof,
sizeof(&array[0]),(因为我们都说数组名就是首地址指针,所以我这么表示。)

可以看出,sizeof打印出了80,
即20*4,20个int的字节长度。但是sizeof(&array[0]),还是4,指针的固定长度。喏,一大区别就在这!

好,通过sizeof,
能够很好认识到原来数组和指针还真存在着不同点。现在继续说下通过指针和数组对数组元素访问的不同策略。

由sizeof可以知道,在定义数组时,等同于在内存中连续分配了N长度的空间,数组的首地址代表这段空间的起始点。比如通过array[i]访问时,步骤如下:

  • 移动到 5000+i*4 的地址
  • 取存在这里的值

而通过指针呢? 我们都只是指针中保存的是地址值, 如 int*p = array;
这里,假设p的地址为6000, 它存的值为array的首地址5000, 通过
p[i]访问是,步骤如下:

  • 取指针p中的值5000,移动到该地址
  • 移动到5000+i*4的地址
  • 取存在这里的值

可以看出,多了一个步骤。这个多出来的步骤,其实大家都知道,这也说明了指针的灵活性。

总结

采用《C专家编程》中的总结,我适当修改合并了一些。作者建议我们在自己真正理解数组、指针后,要先自我总结下,再看他的总结。

1、用 a[i]形式的表达式,编译器都解释成*;

2、指针永远是指针,不可改写成数组。你可以通过下标形式访问指针,且必须是你知道指针指向了是一个数组。
毕竟,编译器并不知道 int*指向了什么,一个int数组还是int变量地址。

3、作为函数参数时,数组都被改写成指针的形式来表达,即类似于
p=&a[0];因此,对于编译器而言,参数表中没有数组,只有指针。

4、声明和定义必须匹配!若是定义了数组,在其他文件声明时也必须是数组,指针亦然。

前言

学习C语言,指针绝对是一道大坎,很多人谈指针色变,使用起来小心翼翼的。“一切指针都是纸老虎”
,同时,对我们得“在战略上藐视指针,战术上重视指针”。

本文先剖析下一维数组和指针,多维的情况后序博客继续更新。

文章流程:

1、辨析指针和数组的不同

澳门新葡亰3522网址 ,2、辨析它们相同的时刻

3、总结


指针等同于数组的时候

我们知道,指针充满了灵活性,而数组却是比较死板的东西,这么说来,就必须先理解好数组,才能更好的了解指针,我们先来说下数组。对于C语言来说,任何事物都必须声明,再使用,我们也按这个顺序,先说下声明:

关于字符串数组,指针的左值性

在C语言中,数组的首地址被定义为“不可修改的左值”, 即类似 int * const a
这样的声明,
我们可以通过它修改它指向的内容,却不能把它赋个新值。即:允许a[i]=yyy,而对
a=xxx 却是提示非法的!

指针呢,就看他怎么声明咯, 一般来说,就是 int* p, 我们可以 p=a, p=xxx,
p[i]=yyy ……,都是允许的。

好啦,大概的区别点就是上述表示的了,那我们继续探讨下他们什么时候相同。


数组的声明

  • 1、外部数组的声明
  • 2、数组的定义
  • 3、函数参数的声明,
    这时候,随便你写指针形式还是数组形式,他们都是等同的。

关于字符串数组、指针的初始化

关于字符数组,我们可以这么来初始化:

char *p  = "helloworld";char a[] = "helloworld";

我们来辨析下内部隐含的区别吧:

对于指针p, 系统为我们分配了匿名一个字符串常量,这个常量是只读的,把它的地址给了p, 因此不能通过p[i]修改字符串常量的值。

对于数组a, 系统定义了一个连续的内存块来分配字符串,它的首地址是a,
我们可以通过
a[i]操作来修改某个字符的值。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2020 3522vip 版权所有