10

I recently wrote a function template which takes a reference to a C-array:

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

Assuming T is a char, the length of the C-string is N - 1 due to the null-terminator. I realized I should probably handle the edge-case where N == 0, because then N - 1 would be std::numeric_limits<std::size_t>::max().

So in order to avoid the chaos that might ensue in the rare case that someone passes a zero-length array to this function, I placed a check for N == 0.

However, to my surprise, it seems that a zero-length array is actually not even an array type - or at least, that's what GCC seems to believe. In fact, a zero-length array doesn't even bind to the above function signature, if a function with a pointer-type signature is available as a candidate.

Consider the following code:

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);
}

With GCC 4.3.2, this outputs:

Array
Pointer
Pointer

Oddly, the zero-length array prefers to bind to the function that takes a pointer type. So, is this a bug in GCC, or is there some obscure reason mandated by the C++ standard why this behavior is necessary?

10
  • Out of curiosity, what is the output of printf("%p\n", array2);? Commented Nov 26, 2010 at 22:12
  • In C, a zero-length array type is not permitted. I'm not sure about C++. I'm not sure if this is related to your problem. Commented Nov 26, 2010 at 22:12
  • 1
    @Oli Charlesworth: In C you can use a zero-sized array as the last element of a struct. You can't instantiate such a struct ,but you can cast a chunk of bytes to a pointer to such a struct and access that array within it with an index Commented Nov 26, 2010 at 23:20
  • Zero length arrays do exist in C++. Their type just can't be constructed by the usual T[N] construct. Notably that type can be constructed though by new, so new int[0] is perfectly valid. Commented Nov 27, 2010 at 2:40
  • @Johannes Schaub - I would say zero length arrays don't exist in C++. new int[0] doesn't return an array-type, but rather, a pointer type. Commented Nov 27, 2010 at 2:45

6 Answers 6

10

As arrays must have greater than zero length, if your compiler erroneously accepts a definition of a zero-sized array then you're "safely" outside of the scope of the language standard. There's no need for you to handle the edge case of N == 0.

This is true in C++: 8.3.5 [dcl.array]: If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

Sign up to request clarification or add additional context in comments.

4 Comments

I don't think "undefined behavior" is correct here. The program that tries to define a zero-length array should be ill-formed.
I see. I'm surprised GCC doesn't emit a warning or error about this.
@Chares Salvia: It does for me; are you using -std=c++98 -pedantic?
no I was just compiling with warning flags. But you're right - it emits an error if I use the -pedantic flag.
3

Apparently ISO C forbids 0-length arrays, which is probably affecting how GCC tries to compile stuff. See this question for further details! zero length arrays vs. pointers

1 Comment

according to me ,this not completely true (see my comment on the question)
2

The GCC Manual has a whole thing on zero length arrays. This is a GCC extension as is somewhat analogous to incomplete arrays.

Comments

1

Speaking for C (and probably also C++ in this case), defining a zero-length array is undefined behavior, so GCC probably does this because a) nothing's stopping it, and b) it prevents errors like the ones you're trying to avoid.

Comments

0

Zero-length arrays do not exist in C++. However if they did, here is how you could handle the case:

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";
}

Comments

-2

Zero sized array are only legal in C as the last element of atruct. Anything else is pointless.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.