Question

There is a simple C program.

#include<stdio.h>

int main()
{
    char *s = "abcde";
    printf("%s\n", s);

    printf("%s\n", *s); /* This is wrong */
    return 0;
}

This is my thought:

  1. variable s is a char * pointer to the string abcde. So variable s is a memory address , and the memory address store the string abced.

  2. The %s format string in function printf() is formatting a string. I don't know why s is the string. The variable s is a char * pointer and *s is the string of abcde, isn't it?

Was it helpful?

Solution

In C, "strings" are NUL-terminated arrays of characters.

The code char *s = "abcde"; does two things:

First, it allocates (in read-only program data) some (unnamed) memory, and populates it with "abcde":

 1000   1001   1002   1003   1004   1005
 _________________________________________
|  a   |  b   |  c   |  d   |  e   |  \0  | 
|______|______|______|______|______|______|

Then, in the stack frame of main, a pointer to char is allocated, named s, and its value is initialized with the address of your string. In my example, s = 1000.

 1000   1001   1002   1003   1004   1005
 _________________________________________
|  a   |  b   |  c   |  d   |  e   |  \0  | 
|______|______|______|______|______|______| 

   ^
   |
   |
 s = 1000 

The %s format specifier tells printf to expect the address of a NUL-terminated string as the corresponding argument..

When you pass s, you are doing just that: telling printf that your string lives at address 1000. printf goes to that address, and starts reading the characters there (a, b, c...) until it encounters a NUL ('\0') character, at which point it stops. It has now read your string.

When you pass *s, two things happen. First, the program de-references the pointer. Since it is a pointer-to-char, that means it reads one character from the memory at 1000. The result of this is 'a', which is the decimal number 97. Now, this value is passed to printf (as before), and printf still thinks it's an address. However, 97 is an invalid address, and your program crashes.

If you need to brush up on your understanding of pointers:

OTHER TIPS

and *s is the string of abcde, isn't it?

No. *s is a char, the first char in the string, so it's a. *(s + 1) is b, *(s + 2) is c, and so on. A char* is an address which points, or refers, to some number of chars.

You are lying to printf with that second call and invoking undefined behavior. The character a is passed and interpreted as an address using it's integral value. That's going to lead to bad things.

printf expects a pointer to char when you use the %s format specifier and that's what you have to pass it. So, what ends up happening is that printf reads past (char*)'a' looking for a null terminator. It may or may not find one before segfaulting, but it's UB either way.

Turn your warnings on.

In c, a string is just a string of characters in memory terminated with a null character ('\0') which tells you where the string stops. There are no string objects. As such when you provide a 'string' to printf you pass it a pointer to where the string is held and it figures out the rest.

when printf meet with a string , It automatically put out the string from start address "a" to the end "\0"; This is special. While printf deal with string, it obey this rule. And for a string, "*a" is the first character of the string , not the whole string . So when you want to put out a string , give the start address to printf. "a"."(a+1)"...can help you put out the character you want in the string.

Q: The variable s is a char * pointer and *s is the string of abcde, isn't it?

No.

*s is a specific character pointed to by s. In the question code, it is the character 'a'.

If it helps, *s results in the same character as s[0]. In otherwords, (for the question code) *s is the value of the first character in the array (or string) of characters.


On the other hand, s is a char * that can store an address. It can store any address in memory you like. In the question code, s was initialized to point at a specific static string (or array of characters).

You can print the specific address pointed to by s:

printf("s points to %p\n", s);

You can print the specific character pointed to by s:

printf("The character pointed to by s: %c\n", *s);

You can print the string (or array) of characters pointed to by s:

printf("s points to an array of characters: %s", s);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top