C语言的那些事儿

发布 2021-10-22 13:53:28 阅读 7750

多维数组那回事儿。

2023年2月10日由 edsionte 留言

前面几篇“那回事儿”的文章更强调一维组和指针之间的关系,本文关注的是多维数组,即“数组的数组”。

多维数组。我们可以将多维数组抽象的看作是具有某种类型的一维数组。当“某种类型”为基本的数据类型时,多维数组就退化成普通的一维数组;当“某种类型”仍然为数组时,那么就形成了多维数组。

也就是说任何一个多维数组都可以分解成几个一维数组。

下面通过示例程序来深入了解多维数组ma[2][3]的构成。

view source

print?

由多维数组ma最左维的长度2可知,ma数组包含两个元素ma[0]和ma[1]。数组名ma在表达式中是数组ma首元素的首地址。在**段1中将ma赋值给数组指针p,则p指向多维数组ma的首元素ma[0],则p+1指向第二个元素ma[1]。

其中p是一个数组指针,它指向一个长度为3的数组,则指针p每次移动的偏移量为12。可参考下图:

在**2中对ma取地址并将其赋值给指针r。r现在指向一个“第一维的大小为2,第二维的大小为3的数组”,则r+1将指向下一个这样的数组(尽管这样的数组并不存在)。由此也可得知r每次的偏移量为24。

ma[0]和ma[1]都是一个长度为3的整型数组,现在以ma[0]为例进行说明。ma[0]中包含三个元素ma[0][0],ma[0][1]和ma[0][2]。在**段3中将ma[0]赋值给t,则t指向数组ma[0]的第一个元素a[0][0],则t+1和t+2则依次指向第二个元素和第三个元素。

对多维数组ma的结构有了一定了解后,现在再看上述程序的运行结果:

view source

print?

注意在结果中,p,r和t的值均相同,但是所指向的数据却不同。更具体的说,这三个指针每次移动时的偏移量不同。

多维数组的初始化。

数组的初始化只能在对数组进行声明(具体为定义型声明)时进行。一维数组的初始化很简单,只要将所有初始值放在一个大括号中即可。如果声明数组时未指定数组的长度,则编译器会根据初始值的个数来确定数组的长度。

view source

print?

注意,在最后一个初始值后面可以继续加一个逗号也可以省略,这并不影响数组的长度。

对于多维数组而言,通常使用嵌套的大括号进行多维数组的初始化。由于多维的数组其实是有若干个一维数组构成的,则每个大括号都代表一个一维数组。对于多维数组而言只能省略最左边下标的长度。

view source

print?

可以看到,不使用大括号也可以对多维数组进行初始化,只不过**可读性较差。

它总是迷惑你!

一旦涉及到多维数组,总有些让你迷惑的地方。比如:

view source

print?

对于上面的**,我们最后的迷惑点都可能落在ma[0,1,1]上。难道多维数组可以这样使用吗?如果ma[0,1,1]和ma[0][1][1]等价,那么sizeof(ma[0,1,1])的值就是1。

很可惜这样的猜测是不正确的,正确答案为6。再比如下面的**:

view source

print?

上述**是为数组ma进行初始化,那么ma[0][0]的值是多少?恐怕很多人都会认为是1。不过正确答案是2。

这两个问题都涉及到了逗号表达式。如果你对逗号表达式有基本的了解,那么也就没有上述那种莫名其妙的迷惑了。根据逗号表达式的运算,对于举例1中的ma[0,1,1]实际上等价于ma[1];对于举例2中的初始化其实等价为char ma[3][2] =

参考:c专家编程》 人民邮电出版社;(美)林登( 著,徐波译;

指针和数组的可交换性。

2023年2月7日。

指针和数组是不相同的,但“很多时候”我们总认为指针和数组等价的。不可否认,这两者在某种情况下是可以相互替换的,但并不能就因此而认为在所有情况下都适合。《指针和数组不是一回事儿》系列文章将逐步深入分析指针和数组的不同之处,并解释什么时候指数组等价于指针。

本文属于《指针和数组不是一回事儿》系列文章之三。

虽然前面两篇文章已经说明了数组和指针的不同,但不可否认的是,指针和数组某些可相互交换的用法仍然令人混淆。本文将给出指针和数组可交换的情景,并且分析可交换的原因。

指针和数组可以交换!”

说出这句话并不是毫无根据的,因为在下面的两个举例中使用数组形式和指针形式都可以达到相同的结果。

举例1:view source

print?

在举例1中,指针p指向一个匿名的字符串“edsionte”,这个匿名字符串的占用的内存空间为9个字节;与p指向一个匿名字符串不同,数组str内存储着字符串“edsionte”,占用了9个字节的空间。

现在分别要访问’d',则方法如下。对于指针p,分别可以通过指针形式*(p+1)和数组形式p[1]来访问其所指的数据;对于数组str,分别可以通过指针形式*(str+1)和数组形式str[1]来访问数组内的元素。

我们已经知道指针和数组在内存构造和访问方式上都不同,但为什么它们都分别可以通过指针的方式和数组的方式进行访问?

举例2:view source

print?

在举例2中,getstr_pointer函数和getstr_array函数的功能都是显示一条字符串。但不同的是,前者传入的参数是一个指针,后者传入的参数是一个数组。在主函数中分别调用这两个函数,传入的参数都是数组str。

读书的那些事儿

因为爸爸妈妈经常在厂里不分日夜加班,没有时间陪我。于是,书,便成了我最亲密的伙伴。开始我并不喜欢看书,什么 一千零一夜 格林童话 一点也不感兴趣。有一回,爸爸递给我一本改编版的 三国演义 有精致的插图 优美的语言,我一下就喜欢上了。于是,吃饭时看,睡觉前看,下课了也看,整天捧着不放,和 爸爸去哪儿3...

读书的那些事儿

作者 胡万邦。作文周刊 小学三年级版 2016年第21期。因为爸爸妈妈经常在厂里不分昼夜地加班,没有时间陪我。于是,书便成了我最亲密的伙伴。开始我并不喜欢看书,什么 一千零一夜 格林童话 一点也不感兴趣。有一回,爸爸递给我一本改编的 三国演义 有精致的插图,语言很优美,我一下子就喜欢上了。于是,我吃...

军训的那些事儿

今天是军训的第五天,回想过去四天的军训,心里有许多话要说。早在军训之前就有学姐学长给我们打预防针,说军训会很辛苦,要提前做好准备。我们带着既害怕又期待的心情终于在6月20日迎来了传说中军训。军训第一天,训练的强度不大,那天天气也很好,没有太阳,而且时时还会有风,所以一天下来,没怎么感觉到累。军训的第...