wef*_*fa3 33 c c++ arrays pointers function
我刚刚发现这在C++中是非法的(但在C语言中是合法的):
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))
int accumulate(int n, const int (*array)[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += (*array)[i];
}
return sum;
}
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它编译没有问题使用gcc -std=c89 -pedantic
但无法编译使用g++
.当我尝试使用它来编译它时,g++
我收到以下错误消息:
main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound 'int []'
int accumulate(int n, int (*array)[])
^
main.cpp: In function 'int main()':
main.cpp:18:50: error: cannot convert 'int (*)[9]' to 'int (*)[]' for argument '2' to 'int accumulate(int, int (*)[])'
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
Run Code Online (Sandbox Code Playgroud)
我一直在我的C代码中使用它很长一段时间,我不知道它在C++中是非法的.对我来说,这似乎是一种有用的方法来记录函数采用一个大小未知的数组.
我想知道为什么这是合法的C但是无效的C++.我也想知道是什么让C++委员会决定把它拿走(并打破与C的兼容性).
那么为什么这个合法的C代码是非法的C++代码呢?
use*_*908 35
Dan Saks在1995年的 C++标准化过程中写到了这一点:
委员会决定接受指针或对具有未知界限的数组的引用这样的函数使C++中的声明匹配和重载解析规则复杂化.委员会同意,由于这些功能几乎没有用处并且相当罕见,因此最简单的禁止它们.因此,C++草案现在声明:
如果参数的类型包括指向T未知边界数组的表单指针类型或对未知边界T的数组的引用,则程序格式错误.
小智 29
C++没有C的"兼容类型"概念.在C中,这是对变量的完全有效的重新声明:
extern int (*a)[];
extern int (*a)[3];
Run Code Online (Sandbox Code Playgroud)
在C中,这是对同一函数的完全有效的重新声明:
extern void f();
extern void f(int);
Run Code Online (Sandbox Code Playgroud)
在C中,这是特定于实现的,但通常是对同一变量的有效重新声明:
enum E { A, B, C };
extern enum E a;
extern unsigned int a;
Run Code Online (Sandbox Code Playgroud)
C++没有这些.在C++中,类型可以是相同的,也可以是不同的,如果它们不同,那么它们之间的差异就很少了.
同样的,
int main() {
const char array[] = "Hello";
const char (*pointer)[] = &array;
}
Run Code Online (Sandbox Code Playgroud)
在C中有效,但在C++中无效:array
尽管[]
被声明为长度为6的数组,它pointer
被声明为指向未指定长度数组的指针,这是一种不同的类型.没有来自隐式转换const char (*)[6]
到const char (*)[]
.
因此,指向未指定长度数组的函数在C++中几乎没用,而且几乎肯定是程序员的一个错误.如果从一个具体的数组实例开始,你几乎总是有这个大小,所以你不能将它的地址传递给你的函数,因为你的类型不匹配.
并且在您的示例中也不需要指向未指定长度的数组:在C中编写它的正常方法(在C++中也恰好有效)是
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
被称为accumulate(ARRAY_LENGTH(a), a)
.