何时数组与指针相同
全部做为函数参数的数组名老是能够经过编译器转换为指针。
在其余全部状况下,数组的声明就是数组,指针的声明就是指针,二者不能混淆。
但在语句或表达式中引用时,数组老是能够写成指针的形式,二者能够互换。
然而,数组和指针在编译器处理时是不一样的,在运行时的表示形式也是不同的。
对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址,你应该根据状况作出选择。
为何会发生混淆
当人们学习编程时,一开始老是把全部的代码都放到一个函数里。
随着水平的进步,他们把代码分别放在几个函数中。
在水平继续提升后,他们最终学会了如何用几个文件来构造一个程序。
何时数组和指针是相同的?C语言标准对此做了以下说明:
规则1 表达式中的数组名(与声明不一样)被编译器看成一个指向该数组第一个元素的指针。
规则2 下标老是与指针的偏移量相同。
规则3 在函数参数的声明中,数组名被编译器看成指向该数组的第一个元素的指针。
规则1:“表达式中的数组名”就是指针
规则1和2合在一块儿理解,就是对数组下标的引用老是能够写成“一个指向数组的起始地址的指针加上偏移量。”
(我的认为,表述为“一个指向该数组第一个元素的指针加上偏移量”更明确。)
对数组的引用如a[i]在编译时老是被编译器改写成*(a+i)的形式。
C语言标准要求编译器必须具有这个概念性的行为。
因而,a[6]和6[a]都是正确的。
编译器自动把下标值的步长调整到数组元素的大小。
这就是为何指针老是有类型限制,每一个指针只能指向一种类型的缘由,
由于编译器须要知道对指针进行解除引用操做时应取几个字节,以及每一个下标的步长应取几个字节。
规则2:C语言把数组下标做为指针的偏移量
事实上,下标范围检测被认为并不值得加入到C语言中。
数组下标是定义在指针的基础上的,因此优化器经常能够把它转换为更有效率的指针表达式,
并生成相同的机器指令。
C语言把数组下标改写成指针偏移量的根本缘由是指针和偏移量是底层硬件所使用的基本模型。
为何C语言把数组形参看成指针
之因此要把传递给函数的数组参数转换为指针是出于效率的考虑,
这个理由经常也是对违反软件工程作法的辩解。
咱们倾向于始终把参数定义为指针,由于这是编译器内部所使用的形式。
但从另外一方面,有些人以为int table[]比int *table更能表达程序员的意图。
数组片断的下标
向函数传递数组前面一个位置的地址(a[-1]),这样就可使数组下标从1到N,而不是从0到N-1。
不幸的是,这个手段彻底为标准所不容,因此你千万不要告诉别人是我告诉了你这个方法。
C语言的多维数组
但全部其余语言都把这称为“数组的数组”
C语言里有一种别的语言称为数组的数组的形式,但C语言称它为多维数组。
C语言中的数组就是一维数组,而这个数组的元素能够是另外一个数组。
编译器在编译时会把carrot[i][j]解析为*(*(carrot+i)+j)的形式。
如何分解多维数组
在“数组的数组的数组”中的每个单独的数组均可以看做是一个指针。
这是由于在表达式中的数组名被编译器看成“指向数组第一个元素的指针”。
内存中数组是如何布局的
在C语言的多维数组中,最右边的下标是最早变化的,这个约定称为“行主序”。
如何对数组进行初始化
只可以在数组声明时对它进行总体的初始化。
之因此存在这个限制,并无过硬的理由。
在IEEE754标准浮点数实现中,0.0和0的位模式是彻底同样的。
初始化二维字符串数组:
char vegetables[][9] =
{
"beet",
"barley",
"basil",
"broccoli",
"beanes"
};
一种有用的方法是创建指针数组,字符串常量能够数组初始化值:
char *vegetables[] =
{
"beet",
"barley",
"basil",
"broccoli",
"beanes"
};
source: 《Expert C Programming》