在 Deitel 的《C 语言编程》第 9 版(第 7 章)中,函数声明为
void bubbleSort(int * const array, size_t size)
并且在文本中指定“函数bubbleSort
的标头声明array
为int * const array
而不是 以int array[]
指示bubbleSort
接收一维数组参数。同样,这些符号可以互换;但是,数组符号通常更易于阅读”。由于“数组名称是指向数组第一个元素的常量指针”(引自同一章),并且由于指向非常量数据的常量指针(例如)用 定义int * const myPtr
,因此在处理数组时, array
asint * const array
等同于更紧凑的数组符号是有道理的。
然而,在同一章关于指针的开头,作者指出“当编译器遇到形式为的一维数组的函数参数时int b[]
,编译器会将该参数转换为指针表示法int *b
。这两种形式可以互换”。
因此,根据作者的说法,int * const array
和都int *array
等同于int array[]
。const
如果它们是数组名称,并且根据定义指向数组第一个元素的常量指针,为什么要添加关键字?或者当数组传递给函数时情况是否如此?
部分如此。
void foo(int array[])
意思void foo(int *array)
完全一样int * const array
有所不同:array
是const
指向int
事项状况
const
:const int *array;
-array
是指向const
int
int * const array;
-array
是const
指向int
const int * const array;
-array
是const
指向const
int
不是。数组在表达式中使用或用作函数参数时会退化为指向其第一个元素的指针。但不是
const
指针结论:
做同样的事情
这些:
不要这样做,因为参数具有不同的类型。
这是错误的。数组通常会转换为指向其第一个元素的指针(但并非总是如此),这可能会导致学生将数组视为指针,但事实并非如此。它们之间存在重要区别。
sizeof array
数组和指针是不同的东西,不能互换使用。当数组是 的操作数、是 typeof 运算符的操作数、是 unary 的操作数或用于初始化数组的字符串文字时,sizeof p
数组不会转换为指针。sizeof
&
这是作者在两个方面的错误陈述。首先,将数组参数更改为指针参数称为调整,而不是转换。这是因为 C 中的“转换”是指对值的操作,但这是函数类型的更改,而不是值的转换。其次,调整是在编译器的函数内部表示中执行的。它不是对源代码中使用的符号的调整。编译器会更改其内部数据结构以记录该参数是指针。编译器不太可能实际使用该符号
int b[]
或int *b
记录此信息。您的陈述“由于数组名称是常量指针……”不在引号内,因此您没有将其归因于作者。您引用的文本没有说数组名称是常量指针,我怀疑这本书在任何地方都没有提到这一点。如果是,您应该引用该段落。
引用的文字确实说了“这些符号可以互换”,但那只是在函数参数声明的上下文中,这意味着数组的声明将被调整为参数的声明。这与说数组等同于常量指针不同。
当将数组参数调整为指针参数时,
const
不会添加。在使用 声明的函数主体中void foo(size_t size, int array[])
, 的类型array
为int *
,并且可能会更改。array += 1
将更改为array
指向数组中的下一个元素,并且这是有效的完全定义的 C 代码(前提array
是 尚未指向数组的末尾)。可以通过在括号内
const
放入来声明数组参数: 。然后,此参数声明将被调整为声明指向的指针。const
int array[const]
const
int
Deitel 的措辞和您的理解都有些混乱。
首先,我们来谈谈
实际上确实如此——如果您尝试写入
array
(将其更改为指向其他内容),它将触发诊断。它允许您写入同时不允许
换句话说,它可以防止您意外地破坏
array
函数主体中的指针。这样做不会影响指向的数组,但对于您的函数正常工作来说并不理想。然而,它并不等同于
调整为
不是
使用数组表示法的等效参数声明实际上是
数组名称不是指针;当你将数组声明为
这是您在内存中获得的内容(地址仅用于说明,并不反映任何真实平台):
没有为指针值留出存储空间;
arr
是数组。 在大多数情况下,编译器会将表达式arr
评估为等同于&arr[0]
;此规则的例外情况如下sizeof
、typeof
、typeof_unequal
或 一元&
运算符的操作数;所以如果你有一个数组
你写
编译器生成相当于以下的代码