零长度C数组绑定到指针类型

Cha*_*via 10 c++ arrays

我最近写了一个函数模板,它引用了一个C数组:

template <class T, size_t N>
void foo(T(&c_array)[N]);
Run Code Online (Sandbox Code Playgroud)

假设T是a char,则C字符串的长度N - 1归因于空终止符.我意识到我应该处理边缘情况N == 0,因为那样的N - 1std::numeric_limits<std::size_t>::max().

因此,为了避免在有人将零长度数组传递给此函数的罕见情况下可能发生的混乱,我进行了检查N == 0.

然而,令我惊讶的是,似乎零长度数组实际上甚至不是数组类型 - 或者至少,这是GCC似乎相信的.实际上,如果具有指针类型签名的函数可用作候选,则零长度数组甚至不绑定到上述函数签名.

请考虑以下代码:

template <class T, size_t N>
void foo(T(&array)[N])
{
    std::cout << "Array" << std::endl;
}

void foo(const void* p)
{
    std::cout << "Pointer" << std::endl;
}

int main(int argc, char** argv)
{
    char array1[10] = { };
    const char* pointer = 0;
    char array2[0] = { };

    foo(array1);
    foo(pointer);
    foo(array2);
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 4.3.2,输出:

Array
Pointer
Pointer
Run Code Online (Sandbox Code Playgroud)

奇怪的是,零长度数组更喜欢绑定到采用指针类型的函数.那么,这是GCC中的一个错误,还是C++标准要求的一些模糊原因为什么这种行为是必要的呢?

CB *_*ley 10

由于数组的长度必须大于零,如果编译器错误地接受零大小数组的定义,那么您"安全地"超出了语言标准的范围.没有必要处理边缘情况N == 0.

这在C++中是正确的:8.3.5 [dcl.array]:如果存在constant-expression(5.19),它应该是一个整数常量表达式,其值应大于零.

  • 我不认为"未定义的行为"在这里是正确的.尝试定义零长度数组的程序应该是格式错误的. (2认同)