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

时间:2010-11-26 22:04:55

标签: c++ arrays

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

template <class T, size_t N>
void foo(T(&c_array)[N]);

假设T是char,由于空终止符,C字符串的长度为N - 1。我意识到我应该处理N == 0的边缘情况,因为那时N - 1将是std::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);
}

使用GCC 4.3.2,输出:

Array
Pointer
Pointer

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

6 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分:3)

显然ISO C禁止0长度数组,这可能会影响GCC尝试编译内容的方式。有关详细信息,请参阅此问题! zero length arrays vs. pointers

答案 2 :(得分:2)

GCC Manual在零长度数组上有一个整体。这是一个GCC扩展,有点类似于不完整的数组。

答案 3 :(得分:1)

对于C(在这种情况下可能也是C ++)来说,定义零长度数组是未定义的行为,因此GCC可能这样做是因为a)没有什么能阻止它,并且b)它可以防止像你那样的错误试图避免。

答案 4 :(得分:0)

C ++中不存在零长度数组。但是,如果他们这样做,这就是你如何处理这个案子:

template <bool B, typename T>
struct disable_if;

template <typename T>
struct disable_if<false, T>
{
    typedef T type;
};

template <class T, size_t N>
typename disable_if<N == 0, void>::type foo(T(&c_array)[N])
{
    std::cout << "inside template\n";
}

答案 5 :(得分:-2)

零大小的数组在C中仅作为struct的最后一个元素是合法的。其他任何事都没有意义。