Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I use pointers as strings when declared with double quotes, but not curly braces, in C? [duplicate]

Tags:

c

string

pointers

If I declare and use a pointer like this:

int counter; char *pCow = "pCow goes MOO";  for(counter = 0; counter < 14; counter++)     printf("%c", pCow[counter]); 

it displays the entire string and works and yeah and there is much rejoicing.

However, if I use an initializer like this:

int counter; char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};  for(counter = 0; counter < 14; counter++)     printf("%c", pCow[counter]); 

the program crashes and pCow refuses to moo for my hedonistic pleasure!

3 Warnings. 0 Errors line 11 (near initialization for 'pCow') [enabled by default]   C/C++ Problem line 11 excess elements in scalar initializer [enabled by default]  C/C++ Problem line 11 initialization makes pointer from integer without a cast [enabled by default]   C/C++ Problem 

Lovingly tested in Eclipse CDT.

like image 980
Jawi Mmm Avatar asked Oct 16 '15 05:10

Jawi Mmm


People also ask

What is the relationship between pointers and strings?

There is a relationship between string and pointers. In C++ string means character array. When a character array is declared then only its first element address is stored. The rest of the elements can be accessed with the help pointer to character array.

Can pointers be used on strings?

A pointer to string in C can be used to point to the base address of the string array, and its value can be dereferenced to get the value of the string. To get the value of the string array is iterated using a while loop until a null character is encountered.


2 Answers

In this case, pCow is set to the address of a c-string in static memory:

char *pCow = "pCow goes MOO"; 

In this case, pCow is set to the value 'p' (i.e., 112):

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 

Since the address 112 most likely points into restricted/invalid memory, that causes your program to blow up when you try to access pCow[counter].

The warning "excess elements in scalar initializer" is telling you that it's ignoring all of the stuff after the 'p' since the pointer only needs one value.

The warning "initialization makes pointer from integer without a cast" is telling you that you're using 'p' as a pointer, which probably isn't a good idea...

What you want to do is declare pCow as a character array rather than a character pointer if you want to use the initializer syntax:

char pCow[] = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 
like image 103
DaoWen Avatar answered Oct 12 '22 13:10

DaoWen


"pCow goes MOO" is a string literal and have two different uses. Either you can use it as an initializer to an array:

char aCow[] = "pCow goes MOO"; 

In which case the contents of the string literal are copied into the array.

Or alternatively, you can use a string literal as a stand-alone constant array anywhere in your program. For example strcpy(cow, "pCow goes MOO");. So there's a distinctive difference between these two:

char aCow[] = "pCow goes MOO"; char* pCow  = "pCow goes MOO"; 

In the first case, the literal is copied into the array. In the second case, the literal remains a stand-alone constant in read-only memory, which we point to with a pointer. The former can be modified, the latter cannot.

As for the case of

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 

You are using a pointer, but you have no string literal. Instead you have an initializer list intended for an array. A good compiler would warn you for "excess initializer". The reason that the code compiles is a very odd rule in C which is allowing plain variables to be initialized with braces, for example int x = {1};. So the compiler uses this rule to initialize your pointer to point at the address 'p', which is of course nonsense, and then it discards the rest of the initializer list.

like image 37
Lundin Avatar answered Oct 12 '22 12:10

Lundin