娓娓道来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数组本质


专栏文件夹:


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

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

(0)
上一篇 2022年2月2日 下午12:00
下一篇 2022年2月2日 下午1:00


相关推荐

  • 透彻解读mysql的可重复读、幻读及实现原理

    透彻解读mysql的可重复读、幻读及实现原理目录一 事务的隔离级别二 mysql 怎么实现的可重复读举例说明 MVCC 的实现 MVCC 逻辑流程 插入 MVCC 逻辑流程 删除 MVCC 逻辑流程 修改 MVCC 逻辑流程 查询三 幻读快照读和当前读四 如何解决幻读事务隔离级别有四种 mysql 默认使用的是可重复读 mysql 是怎么实现可重复读的 为什么会出现幻读 是否解决了幻读的问题 一 事务的隔离级别 Re

    2026年3月18日
    2
  • 用FastJson将JSON字符串转Json[通俗易懂]

    用FastJson将JSON字符串转Json[通俗易懂]一、导入jar<!–fastjson–><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.1.15</version></dependency>二、Fas

    2026年4月15日
    4
  • 谷歌浏览器缓存清理怎么弄_如何清理谷歌浏览器缓存

    谷歌浏览器缓存清理怎么弄_如何清理谷歌浏览器缓存清除缓存快捷键Ctrl+Shift+Delete

    2022年8月2日
    7
  • sql prompt工具

    sql prompt工具SQLPrompt是一款拥有SQL智能提示功能和格式化Sql代码插件。可用于的SQLServer和VS。SQLPrompt能根据数据库的对象名称,语法和用户编写的代码片段自动进行检索,智能的为

    2022年7月1日
    35
  • M1 MacBook安装redis

    M1 MacBook安装redisM1MacBookPro 安装 redis1 下载安装包前往 Redis 官网 https redis io download 下载 tar gz 的安装包以下以 redis 6 2 0 tar gz 为例 2 安装 建议 Library Redis 2 1 创建安装文件夹 2 1 1 方法一 打开终端 cd Librarysudom 输入密码 cdRedis2 1 2 方法二 图形界面操作右键访达前往文件夹 Library 创建 Redis 文件夹进入 Redis 文件夹

    2026年3月18日
    1
  • 《大话数据结构》边读边感

    《大话数据结构》边读边感第一章:数据结构绪论数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。数据:是描述客观事物的符号,式计算机可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。数据输入有两个前提:1、可以输入的计算机中;2、能被计算机程序处理数据元素:是组成数据的,有一定意义的基本单位,在计算机中通常作为整体处理。也被称为记录。数据项:一个数据元素可以由若干个数据项组成;数据项数据不可

    2022年6月24日
    26

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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