简体   繁体   中英

Different Types Of Initializing Character Arrays in C

I was learning about pointers and strings. I understood that,

  1. Pointers and Arrays/Strings have similar behaviours.
  2. array[], *array, &array[0]. They all are one and the same.

Why does the three statements in this code work, and char * help one does not?

#include <stdio.h>

void display(char*help){
    for(int i=0; help[i]!='\0'; i++){
        printf("%c", help[i]);
    }
}
int main(){ 
    // char help[] = "Help_Me";                                 //Works 
    // char help[] = {'H','e','l','p','_','M','e','\0'};        //Works
    // char *help = "Help_Me";                                  //Works
    char *help = {'H','e','l','p','_','M','e','\0'};            //Error 
    
    display(help);
}

Error Messages:

warning: initialization of 'char *' from 'int' makes pointer from integer without a cast
warning: excess elements in scalar initializer

array[], *array, &array[0]. They all are one and the same.

No. Presuming array names some array, array[] cannot be used in an expression (except where it might appear in some type description, such as a cast).

array by itself in an expression is automatically converted to a pointer to its first element except when it is the operand of sizeof or the operand of unary & . (Also, a string literal, such as "abc" , denotes an array, and this array has another exception to when it is converted: When it is used to initialize an array.)

In *array , array will be automatically converted to a pointer, and then * refers to the element it points to. Thus *array refers to an element in an array; it is not a pointer to the array or its elements.

In &array[0] , array[0] refers to the first element of the array, and then & takes its address, so &array[0] is a pointer to the first element of the array. This makes it equivalent to array in expressions, with the exceptions noted above. For example, void *p = array; and void *p = &array[0]; will initialize p to the same thing, a pointer to the first element of the array, because of the automatic conversion. However, size_t s = sizeof array; and size_t s = sizeof &array[0]; may initialize s to different values—the first to the size of the entire array and the second to the size of a pointer.

// char help[] = "Help_Me"; //Works

help is an array of char , and character arrays can be initialized with a string literal. This is a special rule for initializations.

// char help[] = {'H','e','l','p','_','M','e','\0'}; //Works

help is an array, and the initializer is a list of values for the elements of the array.

// char *help = "Help_Me"; //Works

help is a pointer, and "Help_Me" is a string literal. Because it is not in one of the exceptions—operand of sizeof , operand of unary & , or used to initialize an array—it is automatically converted to a pointer to its first element. Then help is initialized with that pointer value.

char *help = {'H','e','l','p','_','M','e','\0'}; //Error

help is a pointer, but the initializer is a list of values. There is only one thing to be initialized, a pointer, but there are multiple values listed for it, so that is an error. Also, a pointer should be initialized with a pointer value (an address or a null pointer constant), but the items in that list are integers. (Character literals are integers; their values are the codes for the characters.)

{'H','e','l','p','_','M','e','\0'} is not a syntax that creates a string or an array. It is a syntax that can be used to provide a list of values when initializing an object. So the compiler does not recognize it as a string or array and does not use it to initialize the pointer help .

  1. Pointers and Arrays/Strings have similar behaviours.

Actually, no, I wouldn't agree with that. It is an oversimplification that hides important details. The true situation is that arrays have almost no behaviors of their own, but in most contexts, an lvalue designating an array is automatically converted to pointer to the first array element. The resulting pointer behaves like a pointer, of course, which is what may present the appearance that pointers and arrays have similar behaviors.

Additionally, arrays are objects, whereas strings are certain configurations of data that char arrays can contain. Although people sometimes conflate strings with the arrays containing them or with pointers to their first elements, that is not formally correct.

  1. array[], *array, &array[0]. They all are one and the same.

No, not at all, though the differences depend on the context in which those appear:

In a declaration of array (other than in a function prototype) ,

  • type array[] declares array as an array of type whose size will be determined from its initializer;
  • type *array declares array as a pointer to type ; and
  • &array[0] is not part of any valid declaration of array .

In a function prototype ,

  • type array[] is "adjusted" automatically as if it were type *array , and it therefore declares array as a pointer to type ;
  • type *array declares array as a pointer to type ; and
  • &array[0] is not part of any valid declaration of array .

In an expression ,

  • array[] is invalid;
  • *array is equivalent to array[0] , which designates the first element of array ; and
  • &array[0] is a pointer to array[0] .

Now, you ask,

Why does the three statements in this code work, and char * help one does not?

"Help_Me" is a string literal. It designates a statically-allocated array just large enough to contain the specified characters plus a string terminator. As an array-valued expression, in most contexts it is converted to a pointer to its first element, and such a pointer is of the correct type for use in...

 // char *help = "Help_Me"; //Works

But the appearance of a string literal as the initializer of a char array...

 // char help[] = "Help_Me"; //Works

... is one of the few contexts where an array value is not automatically converted to a pointer. In that context, the elements of the array designated by the string literal are used to initialize the the array being declared, very much like...

 // char help[] = {'H','e','l','p','_','M','e','\0'}; //Works

. There, {'H','e','l','p','_','M','e','\0'} is an array initializer specifying values for 8 array elements. Note well that taken as a whole, it is not itself a value, just a syntactic container for eight values of type int (in C) or char (in C++).

And that's why this...

 char *help = {'H','e','l','p','_','M','e','\0'}; //Error

... does not make sense. There, help is a scalar object, not an array or a structure, so it takes only one value. And that value is of type char * . The warnings delivered by your compiler are telling you that eight values have been presented instead of one, and they have, or at least the one used for the initialization has, type int instead of type char * .

Pointer is not the array and it cant be initialized like an array. You need to create an object, then you can assign its reference to the pointer.

char *help = (char[]){'H','e','l','p','_','M','e','\0'}; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM