MSVC中数组与指针函数参数的奇特行为及合规性疑问
问题解答
1. MSVC的该行为是否符合C++标准?
不符合。
根据C++标准,函数参数列表中的数组类型会被自动调整为指向数组元素类型的指针,也就是说:
void foo(double a[3]);
会被等价转换为:
void foo(double *a);
二者属于完全等价的函数声明,编译器应当将它们视为同一个函数,生成相同的名称修饰符号。
MSVC将数组参数修饰为double * const(对应修饰名中的Q),而普通指针参数修饰为double *(对应P),这是违背标准的行为——标准中并没有规定数组退化为指针时要添加顶层const限制。
2. 顶层const修饰符对链接器是否有意义?
通常没有意义,但MSVC的这里属于非标准的特殊情况。
C++标准明确:函数参数的顶层const不会影响函数的链接签名。例如:
void bar(int); void bar(const int);
这两个声明会被视为同一个函数,链接器会将它们解析为同一个符号。因为顶层const仅限制函数内部对参数的修改,不影响函数的调用方式(传递int或const int都能匹配),所以不需要区分链接符号。
而MSVC错误地给数组退化后的指针添加了顶层const,导致它将double a[3]和double *a视为两个不同的函数,进而生成不同的修饰名,最终引发链接错误——这是MSVC自身的非标准实现,而非顶层const在标准中的应有行为。
3. 顶层const的含义是什么?
对于指针类型来说:
double *:指针本身是可变的,函数内部可以修改指针的指向(比如a = &another_double;是合法的)。double * const:指针本身是常量,函数内部不能修改指针的指向,但可以修改指针指向的内容(比如*a = 3.14;仍然合法)。
但按照C++标准,数组参数退化成的指针不应该带有顶层const——数组参数的设计本意只是传递数组的首地址,语法上允许函数内部调整指针的指向(虽然这种调整不会影响原数组)。
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

