Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we declare an array of numbers using integer pointer [duplicate]

char *ch = "delhi";               // valid

int *arr = {1, 2, 3};             // invalid

int *arr = (int[3]){1, 2, 3};     // valid

Why some of the above statements are valid while others are invalid?

like image 254
kumar shivam Avatar asked Apr 24 '16 07:04

kumar shivam


People also ask

Why can't we increment an array like a pointer?

It's because array is treated as a constant pointer in the function it is declared. There is a reason for it. Array variable is supposed to point to the first element of the array or first memory instance of the block of the contiguous memory locations in which it is stored.

How do you declare a pointer to an array of pointers to int?

To declare a pointer to an array type, you must use parentheses, as the following example illustrates: int (* arrPtr)[10] = NULL; // A pointer to an array of // ten elements with type int. Without the parentheses, the declaration int * arrPtr[10]; would define arrPtr as an array of 10 pointers to int.

Can we add integers in pointer?

You can only add or subtract integers to pointers. When you add (or subtract) an integer (say n) to a pointer, you are not actually adding (or subtracting) n bytes to the pointer value. You are actually adding (or subtracting) n-times the size of the data type of the variable being pointed bytes.

What is difference between pointer to array and array of pointers?

Here is a list of the differences present between Pointer to an Array and Array of Pointers. A user creates a pointer for storing the address of any given array. A user creates an array of pointers that basically acts as an array of multiple pointer variables. It is alternatively known as an array pointer.


3 Answers

Disclaimer too: I'm answering the question for C++, and I think the answer won't apply to C, in many aspects.

In short, pointer and array are different things.

In c++,

int *arr = {1, 2, 3}; is invalid because pointer couldn't be initialized via list initialization.

int *arr = (int[3]){1, 2, 3}; is valid because array could be initialized via list initialization, and aggregate initialization will be appied for array actually. For this case, a temporary array will be constructed and then decayed to int* and assigned to arr. Note that the temporary variable will be destroyed after the statement so arr will be dangled after that.

char *ch = "delhi"; is not valid from c++11, const char* ch = "delhi" is valid. "delhi" is a string literal with type const char[6], and then decayed to const char* and assigned to ch. Because string literal has static storage duration and ch won't be dangled.

Note that it's not the special rule for int pointer, it's same for char pointer too. const char* ch1 = { 'd', 'e', 'l', 'h', 'i', '\0'}; will fail too.

like image 124
songyuanyao Avatar answered Oct 20 '22 08:10

songyuanyao


char *ch = "delhi";               // valid

This uses a string literal. The compiler generates a static c-string and assigns its starting address to ch. This syntax is special for strings, and has been introduced for the convenience of avoiding typing something like char ch[] = {'d', 'e', 'l', 'h', 'i', '\0'}; every time.

int *arr = {1, 2, 3};             // invalid

{1, 2, 3} is an array initializer, or a std::initializer_list starting from c++ 11. In the first case, the array initializer is not an 'array literal' but a special convenience syntax that is understood by the compiler and applies to arrays only (int* and int[] are slightly different types). In the c++ 11 case you simply don't have conversion from std::initializer_list<T> to T*.

int *arr = (int[3]){1, 2, 3};     // valid

In this case you are telling the compiler to generate a temporary int[3] array, initialize it with the list, and assign its address to arr. Valid, but you should get a warning that you are taking the address of a temporary object or something like that.

EDIT (errata corrige):

The first part of the answer seems to imply that a string literal and a char[] are the same thing. This was unintended, hopefully the part "The compiler generates a static c-string..." and the remark on the second paragraph avoided this misunderstanding in most cases.

The statement "{1, 2, 3} is a std::initializer_list in c++ 11" is not correct. "{1, 2, 3}" is a braced-list-initializer, which is not a type per se. It is a syntactical element that can initialize certain types depending on the context.

like image 23
Emerald Weapon Avatar answered Oct 20 '22 10:10

Emerald Weapon


Disclaimer: I'm answering the question for C++ - some of the reasoning might also apply to C, but I haven't checked the latter.

String literals (the right side of your first example) are (in c++) const char arrays with static storage duration. This means the compiler puts them somewhere in a fixed position in memory that remains valid during the whole execution of your program. As a result, you can assign them to a pointer just like any other array (storing the address of the first element).

Your particular example won't work in c++11 and later, because ch would actually have to be of type const char*. In C-however - and to the best of my knowledge - string literals are arrays of type char (non const), so you can also assign them to a normal char ptr and c++ versions prior to c++11 allowed this assignment for campatibility reasons.

The second line is invalid C++ code for multiple reasons: Contrary to the first line, the right side is not an array, so array to pointer decay doesn't work here. Now you can initialize a pointer with and initializer list, but only if

  1. It has only one element
  2. The the element is of the appropriate type (e.g. a pointer to int or nullptr)

however, the meaning would be totally different compared to the first example: you wouldn't initialize the pointer with the address of an element in the initializer list but just with a copy

Now in the third example (which will be rejected by a c++ compiler by the way, but is OK for const int* and const int[]) I believe you are creating a temporary array that is initialized by copying the contents of the initializer list (the integer literals) and then assigning it to a pointer. Imho this should produce a dangling pointer as soon as the end of the statment is reached, but I'm not 100% sure of it.

like image 43
MikeMB Avatar answered Oct 20 '22 08:10

MikeMB