不是数组的地址,也不是所有元素的地址也不变吗?
如果是这样,请在如下的声明中说明:
char *const argv[]
不是const
限定词的冗余吗?
答案 0 :(得分:7)
没有
首先,const
和"常数"实际上是C中的两个不同的东西,即使const
关键字显然来自单词"常数"。 常量表达式是可以在编译时计算的表达式。 const
真的意味着"只读"。例如:
const int r = rand();
完全合法。
是的,数组的地址 - 就像任何对象的地址一样 - 是只读的。但这并不意味着数组的值(由其元素的值组成)是只读的,任何其他对象都必须是只读的。
考虑这三个声明:
char *arr1[10];
char *const arr2[10];
const char *arr3[10];
arr1
是指向char
的10个元素的指针数组。您可以修改char*
元素和,您可以修改这些元素指向的对象。
arr2
是一个const
(只读)指向char
的数组。这意味着您无法修改数组的char*
元素(一旦它们被初始化) - 但您仍然可以修改这些元素指向的char
个对象或数组
而arr3
是指向const char
的指针数组;您可以修改数组元素,但不能修改它们指向的内容。
现在您使用名称argv
的事实表明您正在谈论main
的第二个参数,这对此有一些巨大的影响。该语言指定main
的第二个参数是
char *argv[]
或等同地
char **argv
没有const
。您可能可以添加一个,但最好遵循标准指定的格式。 (更新:我从您的评论中看到您已经询问argv
getopt()
char * const argv[]
参数,该参数定义为{{1}}。)
由于它是一个定义为数组的参数,另一个规则起作用:定义为某种类型数组的参数是"调整"指向该类型的指针。 (此规则仅将 应用于参数。)这不是运行时转换。函数不能有数组类型的参数。
C中数组和指针之间的关系可能令人困惑 - 而且那里有很多错误的信息。要记住的最重要的事情是数组不是指针。
comp.lang.c FAQ的第6节是对细节的极好解释。
答案 1 :(得分:3)
不是数组的地址,也是其所有元素的地址 不管怎么说?
是的,C
中的任何对象都是如此。回想一下,通过这里的对象,我们指的是存储器中具有值并由标识符引用的位置。标识符在其整个范围内绑定到固定的内存位置,您无法更改它。您可以更改对象的值。
int a = 4;
a = 6; // legal. you can change the value of the object
&a = 23456; // illegal. you cannot change the address of the object
类似地,数组也是一个对象,其每个元素都有一个固定的内存地址。但是,数组元素保存的值与元素的地址无关。
请注意,如果声明出现在函数参数列表中,则以下内容是等效的
char *const argv[]
char *const *argv
这意味着argv
是指向类型为char *const
的对象的指针,即指向字符的常量指针。很明显char *const *argv
和char **argv
是不同的。所以让我们再举一个例子。
char *const argv[10];
上述语句将argv
定义为一个10
常量指向字符的数组。这意味着您必须初始化数组,以后不能将指针更改为指向不同的字符。但是,这与数组元素的地址无关。
char c = 'A';
char d = 'B';
char *const argv[2] = {&c, &d};
argv = &c; // illegal. you cannot the change the address of an object
argv[0] = &d; // illegal. you cannot change the value of the array element
*argv[0] = 'C'; // legal. you change the value pointed to by the element
如果没有const
限定符,char *argv[2]
表示一个2
指向字符的数组。
这与我们如上所述具有const
限定符的情况明显不同。因此,回答第二个问题,不,const
限定符不是多余的。这是因为const
限定符限定了数组元素的类型。
答案 2 :(得分:2)
不,不是。 char *const argv[]
是一个指向char
的常量指针数组。所以const
使数组中的指针保持不变(你不能将它们改为指向内存中的其他字符串)。