C中的常量指针数组是什么?

Lav*_*vya 5 c arrays pointers const function

不是数组的地址,因此它的所有元素也不变吗?

如果是这样,在如下的声明中:

char *const argv[] 
Run Code Online (Sandbox Code Playgroud)

是不是const限定词多余?

Kei*_*son 9

没有.

首先,const"常量"实际上是C中的两个不同的东西,即使const关键字显然来自单词"常量".甲常量表达式是一个可以在编译时进行评估.const真的意思是"只读".例如:

const int r = rand();
Run Code Online (Sandbox Code Playgroud)

是完全合法的.

是的,数组的地址 - 就像任何对象的地址一样 - 是只读的.但是,这并不意味着该的阵列(其包括其元素的值的)是只读的,比任何其他对象的任何更必然是只读的.

考虑这三个声明:

char *arr1[10];
char *const arr2[10];
const char *arr3[10];
Run Code Online (Sandbox Code Playgroud)

arr1是一个10元素的指针数组char.您可以修改char*元素,也可以修改这些元素指向的对象.

arr2是一个const(只读)指针数组char.这意味着您无法修改char*数组的元素(一旦它们被初始化) - 但您仍然可以修改char这些元素指向的对象或数组.

并且arr3是一个指针数组const char; 您可以修改数组元素,但不能修改它们指向的内容.

现在您使用该名称的事实argv表明您正在谈论第二个参数main,这对此有一些巨大的影响.该语言指定main第二个参数是

char *argv[]
Run Code Online (Sandbox Code Playgroud)

或者,等效地,

char **argv
Run Code Online (Sandbox Code Playgroud)

没有const.你可以很可能逃脱增加一个,但它是最好按照标准规定的形式.(更新:我从您的评论中看到您询问的argv参数是什么getopt(),定义为char * const argv[].)

由于它是一个定义为数组的参数,另一个规则起作用:定义为某种类型数组的参数被"调整"为指向该类型的指针.(此规则适用于将参数).这不是一个运行时转换.函数不能具有数组类型的参数.

C中的数组和指针之间的关系可能令人困惑 - 而且那里有很多错误的信息.要记住的最重要的事情是数组不是指针.

comp.lang.c FAQ的第6部分是对细节的极好解释.

  • 那么"只读"你实际上是指"只写一次",对吗? (4认同)
  • @EricLippert:"只读"是指无法通过引用其名称来修改对象.可以初始化`const`对象.您无法通过为其指定值来修改它 - 甚至不能修改一次.`const int n = 42;`有效; `const int n; n = 42;`不是. (3认同)

aja*_*jay 5

无论如何,数组及其所有元素的地址不是常量吗?

是的,对于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
Run Code Online (Sandbox Code Playgroud)

同样,数组也是一个对象,它的每个元素都有一个固定的内存地址。但是,数组元素持有的值与元素的地址无关。

请注意,如果声明出现在函数参数列表中,则以下内容是等效的

char *const argv[]
char *const *argv
Run Code Online (Sandbox Code Playgroud)

这意味着它argv是指向类型为 的对象的指针char *const,即指向字符的常量指针。很明显,char *const *argvchar **argv是不同的。那么让我们再举一个例子。

char *const argv[10];
Run Code Online (Sandbox Code Playgroud)

上面的语句定义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
Run Code Online (Sandbox Code Playgroud)

没有const限定符,char *argv[2]意味着2指向字符的指针数组。这与我们const上面解释的限定符的情况明显不同。因此,要回答您的第二个问题,不,const限定词不是多余的。那是因为const限定符限定了数组元素的类型。

  • 感谢您的出色澄清和宝贵的额外指示! (2认同)