3

What's wrong with the initialization of s2 in the code below?

#include <stdio.h>

int main()
{
  char *s1 = "foo";
  char *s2 = {'f', 'o', 'o', '\0'};

  printf("%c\n", s1[1]);
  printf("%c\n", s2[1]);
  return 0;
}

I thought because I could initialize s1 the way I did above, the initialization of s2 should work fine as well.

But this code leads to compile-time warnings as well as run-time segmentation fault.

$ gcc foo.c
foo.c: In function ‘main’:
foo.c:6: warning: initialization makes pointer from integer without a cast
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
$ ./a.out
o
Segmentation fault (core dumped)

3 Answers 3

4

A better question to ask is why you can initialize a pointer with a string literal, because inability to initialize a pointer using an array initializer should come as no surprise: after all, arrays are not pointers.

String literals, however, are special. C lets you use them to initialize both arrays and pointers in order to provide a convenient syntax for creating null-terminated strings. That is why your first syntax works with both an array of characters and a character pointer.

Sign up to request clarification or add additional context in comments.

Comments

4

Yes, because {'f', 'o', 'o', '\0'}; is a brace-enclosed intializer list. It cannot be used to initialize a pointer variable, in any way. However, it can be used to initialize a char array, like

 char s2[] = {'f', 'o', 'o', '\0'};

because arrays are not pointers.

For your case, you can try using a compound literal instead as a workaround.

Something like

  char *s2 = (char []){'f', 'o', 'o', '\0'};

Just to add some additional info, which can arise after reading this answer, like then why / how it is possible to initialize an array with string literal, like

  char s3[] = "Hello";

is possible, because as mentioned in C11, chapter §6.7.9, initialization

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

3 Comments

Are we are creating an intializer list and then typecast, so it will create this unnamed(internally named) [ ] temporarily ? and assign its address to s2? I mean regarding your answer char *s2 = (char []){'f', 'o', 'o', '\0'};
@SuvP: Compound literals are lvalues with automatic storage duration that extends until the end of the containing scope.
@SuvP s2 is an array and cannot be assigned . We're just creating an unnamed object with automatic storage here to initialize the elements of s2. FWIW, in global scope, a compound literal will have static storage duration.
1

Designated initializers {} initialize the data on the left of =. For example

int a[6] = { 0, 0, 15, 0, 29, 0 };

initializes array of 6 integers, that is why each of elements in initializer list is integer.

In your example of

char *s2 = {'f', 'o', 'o', '\0'};

you would therefore attempt to initialize pointer to char with integer values of characters which is not what you wanted. To initialize character array you can use

char s2[] = {'f', 'o', 'o', '\0'};

syntax, or

char s2[] = "foo"; /* also allowed in C, as dasblinkenlight noted - the better
                    * question would be why this works and Sourav Ghosh gave
                    * the answer */

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.