I was learning about pointers and strings. I understood that,
- Pointers and Arrays/Strings have similar behaviours.
- 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
CodePudding user response:
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
.
CodePudding user response:
- 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.
- 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[]
declaresarray
as an array oftype
whose size will be determined from its initializer;type *array
declaresarray
as a pointer totype
; and&array[0]
is not part of any valid declaration ofarray
.
In a function prototype,
type array[]
is "adjusted" automatically as if it weretype *array
, and it therefore declaresarray
as a pointer totype
;type *array
declaresarray
as a pointer totype
; and&array[0]
is not part of any valid declaration ofarray
.
In an expression,
array[]
is invalid;*array
is equivalent toarray[0]
, which designates the first element ofarray
; and&array[0]
is a pointer toarray[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 *
.
CodePudding user response:
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'};