娓娓道来c指针 (3)指针和数组「建议收藏」

娓娓道来c指针 (3)指针和数组

大家好,又见面了,我是全栈君。

                            (3)指针和数组

在c中指针和数组似乎有着千丝万缕的关系。事实上它们不是一回事:指针是指针,数组是数组。两者不同样。

说它们有关系,只是是由于常见这种代码:

int main()
{
	int array[] = {1,2,3,4,5};
	int n = sizeof(array) / sizeof(int);
	int *p = array;
	int i;
	for (i = 0; i < n; i++)
		printf("p[%d]...%d\n", i, p[i]);
	system("pause");
	return 0;
}

执行

娓娓道来c指针 (3)指针和数组「建议收藏」

在上面的代码中,指针和下标运算符的结合使用,给人一种指针和数组是一样的感觉。

本质是:数组名是一个指向数组起始元素的常量指针。这也是数组和指针的唯一联系!

之所以能够使用 p[i] 来訪问数组中的元素,是由于在编译器中 p[i] 被解释为 *(p+i),这仍然是指针的功能。

对编译器而言,用p[i]表达*(p+i)的含义是没有意义的。它仅仅是为了让人看着舒服。用着方便。这是语法糖

    p[i]是*(p+i)的简单写法,实际上。至少对于编译器来说,[]这种运算符全然能够不存在。

    但是对于人类来说。*(p+i)的写法在解读上比較困难,写起来也麻烦(键入量大)。因此,c语言引入[]运算符。

    就像这样。这些不过为了让人类easy理解而引入的功能,的确能够让我们感受到编程语言的甜蜜味道(easy着手),有时我们称这些功能为语法糖(syntax sugar 或者 syntactic sugar)。

以上摘自《征服c指针》。借此推荐这本书。书中一针见血地指出:仅仅有在声明语句中。[]才表达数组的含义。在表达式中,[]与数组无关!

总结起来就是。看似数组的使用方法:p[i],事实上是*(p+i)的语法糖。p仍然是指针,与数组并无关系。


指针和数组的不同之处,还能够从以下的样例看出

void fun(int array[5])
{
	printf("  sizeof(array)...%d\n", sizeof(array));
}
int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	printf("  sizeof(array)...%d\n", sizeof(array));
	fun(array);
	return 0;
}

执行

娓娓道来c指针 (3)指针和数组「建议收藏」

从执行结果看,函数形參尽管用数组的方式进行了声明,但仍然被当做指针。这揭示了c语言中传递数组时的规则:传递过去的是地址,是指向数组起始元素的地址。之所以这样,基于两点;

  1. 从效率上考虑。若是把整个数组赋值过去,太耗时,也耗空间。还不如传地址过去,使用同一份内容。
  2. 在c语言设计之初,赋值操作就仅限于基本类型(char、int、float……),而数组是聚合类型。
这给我们的编程启发是:传递数组时,不要忘了把数组大小也传递过去。否则,函数那边因为不知道数组大小,极易越界。

应这样设计函数 void fun(int *array, int n),n是数组大小。

另一点须要指出。即使函数被设计成void fun(int array[5], int n),array依旧被看成是指针。

也就是说即使数组带了长度。该长度也会被编译器忽略掉。一句话:形參中的数组统统看成指针。

既然如此,还不如直接写成void fun(int *array, int n)。指针的形式。更能表达本意。


再思考:假设p[i]是*(p+i)的意思。因为加法具有交换律:p+i=i+p,那么i[p]相同能够表达p[i]的意思,是这种吗?实验验证:
int main(){	int array[] = { 1, 2, 3, 4, 5 };	int n = sizeof(array) / sizeof(int);	int *p = array;	int i;	for (i = 0; i < n; i++)		printf("  %d[p]...%d\n", i, i[p]);	return 0;}

执行

娓娓道来c指针 (3)指针和数组「建议收藏」
实验证明,我们的猜想是正确的:p[i]确实是*(p+i)的语法糖。i[p]这种写法是否非常逆天呢!

总结:仅仅有在函数形參中,仅有这一种情况,声明的数组。如 int array[]会被看作是指针。其他情况下,指针与数组并无联系。

&array的含义
另一点,对于 int array[5];array表示指向数组起始元素的指针,那么&array又是什么呢?实验下:
int main(){	int array[] = { 1, 2};	printf("   array...%p\n", array);	printf("  &array...%p\n", &array);	printf("&array+1...%p\n", &array+1);	return 0;}

执行

娓娓道来c指针 (3)指针和数组「建议收藏」
分析实验结果:0031FCEC与0031FCE4相差8。而sizeof(array)就是8。
结论就是:array和&array都是指针。但类型不同。array的类型是int*。而&array的类型是int(*)[2]。

array是指向普通int类型的指针;&array是数组指针,该数组元素是int类型的,且数组大小是2。

至于array和&array两者的值是一样的,应该非常好理解。

补充
标量(scalar):简单讲,标量就是指char、int、double和枚举类型等数值类型,再加上指针。

至于数组、结构体和共用体这样将多个标量进行组合的类型,我们称之为聚合类型(aggregate)。

那么为什么int(*)[2]表示的是数组指针呢?这须要透彻理解c的声明语法。又比方。二维数组(更甚者,多维数组)的数组名又是什么类型的指针呢?这须要了解c中数组的实际含义,后序解说。

很多其它指针和数组的内容见(5)c数组本质


专栏文件夹:


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115590.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Could not download kotlin-reflect.jar 完美解决

    Could not download kotlin-reflect.jar 完美解决

  • Vue + ElementUI 后台管理系统实现顶部一级菜单栏,左侧二级菜单栏

    Vue + ElementUI 后台管理系统实现顶部一级菜单栏,左侧二级菜单栏一、要求后台管理系统页面的整体结构如图:实现顶部一级菜单和左侧二级菜单进行响应,选哪个一级菜单时,左侧菜单栏有相对应下的二级菜单,产生联动效果。然后选不同的二级菜单,主体内容区域展示对应内容。二、效果图三、具体操作实现1、用vue-cli创建的Vue项目后,自己再手动搭建项目的基本目录结构,如图:2、创建一个公共组件Whole.vue来实现整体页面结构的布局,通过div来进行区域定位和大小设定。使用el-menu组件的mode…

  • dpkg 命令详解[通俗易懂]

    dpkg 命令详解[通俗易懂]名词解释    “dpkg”是“DebianPackager”的简写。为“Debian”专门开发的套件管理系统,方便软件的安装、更新及移除。所有源自“Debian”的“Linux”发行版都会使用“dpkg”,例如“Ubuntu”、“Knoppix”等。名词由来    dpkg是Debian软件包管理器的基础,它由伊恩·默多克于1993年创

  • Maximal Information Coefficient (MIC)最大互信息系数详解与实现「建议收藏」

    Maximal Information Coefficient (MIC)最大互信息系数详解与实现「建议收藏」MICMIC即:MaximalInformationCoefficient最大互信息系数。使用MIC来衡量两个基因之间的关联程度,线性或非线性关系,相较于MutualInformation(MI)互信息而言有更高的准确度。MIC是一种优秀的数据关联性的计算方式。本篇文章将会详细介绍MIC的算法原理,优缺点以及Python的具体实现方式,并给出一个可视化方案。互信息?互信息(Mut…

  • MyEclipse 配置SVN插件

    MyEclipse 配置SVN插件MyEclipse6.5: 1.打开Myeclipse,在菜单栏中选择Help→SoftwareUpdates→FindandInstall; 2.选择Searchfornewfeaturestoinstall,点击Next进入下一步; 3.点击“NewRemoteSite”按钮,在弹出的对话框中输入:      name:svn

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号