How Can a Char Pointer Be Initialized with a String (Array of Characters) But an Int Pointer Not with an Array of Integer

Why can a char pointer variable be initialized to a string but an int pointer variable can not be initialized to an array of integers?

a C-style string is simply an array of chars

Correct.

An array is simply a shorthand version of referring to the pointer (which stores the first value of the array) and an offset.

No, not really.

the method cout interprets the argument szstring as a string type and prints out all the characters until the NUL character

cout is not a "method", but its operator<< works this way yes.

Why can a char pointer variable be initialized to a string but an int pointer variable can not be initialized to an array of integers?

The simple answer is that string literals are special, otherwise we would not be able to use them.

In many ways, including this way, the language standards dictate special handling for both string literals and char*s.

why can I not initialize an int type pointer to the first element in an array of integers

C++ could have ultimately extended the syntax of other pointer initialisations to do a similar thing, but it didn't actually need to because instead we have the far superior:

std::vector<int> myInts{1,2,3};

How can a char pointer be initialized with a string (Array of characters) but an int pointer not with an array of integer?

In case of you're trying to initialize an int * with

  {1,2,3,4,5};

it is wrong because {1,2,3,4,5};, as-is, is not an array of integers. It is a brace enclosed list of initializer. This can be used to initialize an int array (individual elements of the array, to be specific), but not a pointer. An array is not a pointer and vice-versa.

However, you can make use of a compound literal to initialize an int *, like

int * a = (int []){1,2,3,4,5};

Pointer to Char Initialization in C

There is one thing you need to learn about constant string literals. Except when used to initialize an array (for example in the case of v1 in your example code) constant string literals are themselves arrays. For example if you use the literal "AB" it is stored somewhere by the compiler as an array of three characters: 'A', 'B' and the terminator '\0'.

When you initialize a pointer to point to a literal string, as in the case of str1 and str2, then you are making those pointers point to the first character in those arrays. You don't actually create an array named str1 (for example) you just make it point somewhere.

The definition

char *str1 = "AB";

is equivalent to

char *str1;
str1 = "AB";

Or rather

char unnamed_array_created_by_compiler[] = "AB";
char *str1 = unnamed_array_created_by_compiler;

There are also other problematic things with the definitions you show. First of all the arrays v3, v4, v5 and v6. You tell the compiler they will be arrays of two char elements. That means you can not use them as strings in C, since strings needs the special terminator character '\0'.

In fact if you check the sizes of v1 and v2 you will see that they are indeed three bytes large, once for each of the characters plus the terminator.

Another important thing you miss is that while constant string literals are arrays of char, you miss the constant part. String literals are really read-only, even if not stored as such. That's why you should never create a pointer to char (like str1 and str2) to point to them, you should create pointers to constant char. I.e.

const char *str1 = "AB";

Different Types Of Initializing Character Arrays in C

  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 *.

Why do strings work, but character and int arrays do not work in a pointer array?

This

int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
st,
st2
};

Is three arrays: two of integers (with their own storage), and one array of two elements which are pointers to the first two arrays.

However, this is not valid:

int *day_tab[]= {
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}
};

As before you have declared an array of pointers to integers, but pointers to what? Those braced lists are not storage locations, they cannot be pointed to.

Your final example is basically valid but dangerous:

char *day_tab[]= {
"01",
"01"
};

It is an array of two pointers to characters, and those pointers are initialized with string literals. String literals are very special in that they are actually stored somewhere, usually in read-only memory, and they can be shared (so the "01" string used twice can be stored just once). Braced lists don't have this feature in C, it's only for string literals.

The reason the final code is dangerous is that it is char* not const char*. The non-const type is accepted for reasons of backward compatibility but is not a good idea because modifying the data in a literal string is not allowed. So you're setting yourself up for a potential disaster if you actually use those pointers to write to the "01" string storage.

Initializing a char pointer C++

String literals are really arrays of constant characters (with the including terminator).

When you do

const char *cp = "Hello world";

you make cp point to the first character of that array.


A little more explanation: Arrays (not just C-style strings using arrays of char but all arrays) naturally decays to pointers to their first element.

Example

char array[] = "Hello world";  // An array of 12 characters (including terminator)
char *pointer1 = &array[0]; // Makes pointer1 point to the first element of array
char *pointer2 = array; // Makes pointer2 point to the first element of array

Using an array is the same as getting a pointer to its first element, so in fact there is an address-of operator & involved, but it's implied and not used explicitly.

As some of you might have noted, when declaring cp above I used const char * as the type, and in my array-example with pointer1 and pointer2 I used a non-constant plain char * type. The difference is that the array created by the compiler for string literals are constant in C++, they can not be modified. Attempting to do so will lead to undefined behavior. In contrast the array I created in my latter example is not constant, it's modifiable and therefore the pointers to it need not be const.

Why can you initialize a string pointer as a string literal, but not as an array?

Why can you initialize a string pointer as a string literal, but not as an array?

Because {'a', 'b', 'c', '\0'} is not an array; it is a list of values to put in the thing being initialized.

The syntax {'a', 'b', 'c', '\0'} does not stand for an array in C. People see it being used to initialize arrays, but, when used in that way, it is just a list of values. It could also be used to initialize a structure, because it is just listing values to put into the thing being initialized. It is not, by itself, an array.

In char *word2 = {'a', 'b', 'c', '\0'};, it does not make sense to initialize word2 with the values 'a', 'b', 'c', and '\0'. It is just one pointer and should be initialized with one value. Giving a list of four values to initialize one thing does not make sense.

In char *word2 = "abc";, "abc" is not a list of values. It is a string literal. A string literal defines a static array that is filled with the characters of the string. And then the string literal is automatically converted to a pointer to its first element, and it is this pointer that is used to initialize word2.

So char *word2 = "abc"; does two things: The string literal defines an array, and the initialization sets word2 to point to the first element of that array. In contrast, in char *word2 = {'a', 'b', 'c', '\0'};, there is nothing to define an array; the list of values is just a list of values.

Comparing this to array initializations, in char word2[] = {'a', 'b', 'c', '\0'};, the array is initialized with a list of values, which is fine. However, in char word1[] = "abc";, something special happens. C 2018 6.7.9 14 says we can initialize an array of character type with a string literal, and the characters of the string will be used to initialize the elements of the array.



Related Topics



Leave a reply



Submit