Why are char[] and char* as typedefs different, but sometimes… not?

前端 未结 3 1164
遥遥无期
遥遥无期 2020-12-31 09:30

The following observation arose as I was following this question about char[] and char* differences.

#include 

typ         


        
相关标签:
3条回答
  • 2020-12-31 09:51

    The C family is pass-by-value, and the C value of an array is a pointer to its first element. When you pass an item declared to be an array to a function, what's really getting passed is that pointer, and C treats the prototype as if you declared it that way.

    0 讨论(0)
  • 2020-12-31 09:55

    I changed the code so that we could see how calling a f2 changes the type. Before the call the variables are of different type. After the call they have become same

        typedef char ar[];
    typedef char* pr;
    void f2(ar x, pr y)
    {
        cout << is_same<decltype(x), decltype(y)>::value << '\n'; //same type
    }
    
    int main()
    {
        ar data = "data";
        pr ptr = data;
        cout << is_same<decltype(data), decltype(ptr)>::value << '\n'; // different
        f2(data,ptr);
        return 0;
    }
    

    the output is 0 0 .As @jthill, @Dyp and @keith Thompson says this is because of decaying of the array to pointer.

    0 讨论(0)
  • 2020-12-31 10:05

    In C++, as in C, a parameter that's declared to be of array type is adjusted (at compile time) to be of pointer type, specifically a pointer to the array's element type.

    This happens whether the array type is specified directly or via a typedef (remember that a typedef doesn't create a new type, just an alias for an existing type).

    So this:

    typedef char ar[];
    typedef char* pr;
    void f2(ar x, pr y)
    {
        // ...
    }
    

    really means:

    void f2(char* x, char* y)
    {
        // ...
    }
    

    Another rule, also shared by C and C++, is that an expression of array type is, in most but not all contexts, implicitly converted to a pointer to the first element of the array object. Which means that if you define an array object:

    char arr[10];
    

    you can use the name of that object as an argument to a function that takes a char* parameter (which loses the bounds information).

    In C, the cases where this implicit conversion doesn't happen are:

    1. When the array expression is the operand of sizeof (sizeof arr yields the size of the array, not the size of a pointer);
    2. When the array expression is the operand of unary & (&arr is a pointer-to-array, not a pointer-to-pointer); and
    3. When the array expression is a string literal used to initialize an object of array type (char s[] = "hello"; initializes s as an array, not as a pointer).

    None of these cases (or the other cases that occur in C++) appear in your program, so your call:

    f2(data,ptr);
    

    passes two pointer values of type char* to f2.

    Inside f2, the parameter objects x and y are both of type char*, so std::is_same<decltype(x), decltype(y)>::value is true.

    But the types ar and pr are distinct. ar is an incomplete array type char[], and pr is the pointer type char*.

    Which explains your program's output. The weirdness happens because the parameter x, which you defined with the array type ar, is really of type char*, which is the same type as pr.

    0 讨论(0)
提交回复
热议问题