-5
int main()
{
   int *a={1,2,3}; //which value is stored and where it is stored 
   printf("\n%d",*a); //crashes here
}

Please explain why the above is crashing.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
vamshi
  • 183
  • 1
  • 1
  • 8

3 Answers3

5

The posted code has undefined behavior, so it may compile and execute, but the results are unpredictable. One possible outcome is a segmentation fault.

The line:

int *a={1,2,3};

attempts to initialize a pointer to int with an initializer list (which contains too many elements; this should generate a warning), but this initializer list is not an array.

One solution would be to use an actual array:

int arr[] = { 1, 2, 3 };
int *a = arr;

Here arr[] is an incomplete array type. The initializer list is used to initialize the array arr[], and when the end of the initializer list is reached, the array type is completed. Now a is a pointer to the first element of the array arr[], which has type int [3].

Another option, available since C99, is to use a compound literal:

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

Here, the compound literal creates an anonymous array, and a points to the first element of this array. Note that this anonymous array would have automatic storage duration in the case of the posted code, which is to say that it is exists only while program execution is within the main() block. In general, according to §6.5.2.5 5 of the C11 Draft Standard:

If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • One tiny note: As I learned, `int *a={1,2,3};` is a constraint violation and should give an _error_ instead of _warning_ by a conforming compiler. – machine_1 Feb 01 '18 at 17:22
  • @machine_1 -- the Standard only says that an implementation must issue a _diagnostic_ for constraint violations. This may be a warning or an error, but the Standard makes no distinction; that is implementation-specific. – ad absurdum Feb 01 '18 at 17:24
  • @vamshi.: Don't change the selection of answer after you have done it once...it's really strange and awkward for both the person. (Give proper thought before you do it first time - frequently changing is not a good thing in many of the person's opinion). – user2736738 Feb 01 '18 at 17:26
  • 2
    @coderredoc -- I appreciate the support, but OP should accept whichever answer is most helpful to them :) – ad absurdum Feb 01 '18 at 17:27
  • @lurker.: You said *fickle* ? – user2736738 Feb 01 '18 at 18:08
4

First of all from standard

       initializer:
                   assignment-expression
                   { initializer-list }
                   { initializer-list , }

So you are using initializer list.

From standard 6.7.9p11

The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type.

So that's it. int *a={1,2,3} is not legal code.

But even if you try something like this

int *a = {1};

Compiler will comlain about error: invalid conversion from 'int' to 'int*' [-fpermissive].

You can do this though,(But there is not much you can do with this)

int *a = {(int*)1};

But dereferencing this may lead to undefined behavior. (i.e.,segmentation fault).

user2736738
  • 30,591
  • 5
  • 42
  • 56
2

int *a={1,2,3}; here a is a pointer, It's expecting some valid address ,It's the programmer job is to assign some valid address to it so that it couldn't point to random address.

Although it's undefined behaviour but here a is initialized with first element. so its looks like

 int *a = 1;

when you are doing *a, it crashes because you are trying to de-reference invalid address.

Solution is first allocate memory dynamically and then do the operation as

int *a = malloc( 3 * sizeof(int));
        a[0]= 1;
        a[1]= 2;
        a[2]= 3;

        for(int i = 0 ;i< 3 ;i++) {
                printf("\n[%d]\n",a[i]);
        }

Once job is done free the memory to avoid memory leakage as

free(a);

Note : An initializer list { } is different from a string literal " ".

int *a = {1}; /* a didn't get any address */
int *a = "1"; /* a gets address*/
Achal
  • 11,821
  • 2
  • 15
  • 37