9

Why does this code work? I would expect that I would need to dereference ptr, printf("%s\n", *ptr); before I could print it out, but I get a Segmentation Fault if I try to do it that way.

#include <stdio.h>

int main(int argc, char *argv[])
{
        char name[] = "Jordan";
        char *ptr = name;
        printf("%s\n", ptr);
}

Hope you guys could give me some insight.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
user1787531
  • 789
  • 4
  • 10
  • 22

6 Answers6

24

When you print string we need starting address of string.

printf("%s\n", ptr);
                ^ address with %s   

it prints chars till \0 nul encounter.

Whereas to print chat int .. we need value variable:

printf("%c\n", *ptr);
               ^ * with %c print first char

Where as in scanf() a string you always need to give address:

scanf("%s", ptr);
            ^ string address

Also for int scanf() a char

scanf("%c", ptr);
            ^ read at first location char address 

Note: Scanf() need address with %c to store a scanned value in memory.

Be careful your ptr points to a constant string so you can't use in scanf.

Why Segmentation fault with following code ?

    printf("%s\n", *ptr);

When you do like this, because of %s printf interprets *ptr as an address, but it's actually not an address and if you treat it as address it points to some location that is read protected for your program(process) So it causes a segmentation fault.

Your ptr via name points to some constant string in memory ("Jordan") as in below diagram:

name 2002
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ 'J' │ 'o' │ 'r' │ 'd' │ 'a' │ 'n' │'\0' │ ........
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
  ^
  |
 ptr = name 

 ==> ptr = 2002
     *ptr = 'J'

In printf("%s\n", *ptr); the *ptr = 'J' and ASCII value of char 'J' is 74 but 74 address is not under your process control and you are trying to read from that memory location and its a memory violation and segmentation fault occurs.

If you compile you code containing printf("%s\n", *ptr); then with proper option say -Wall with GCC you will get a warning like below:

warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’

Says %s need (expects ) an address of type char* but you are putting value

notice:

printf("%s\n",   *ptr);
        ^          ^ argument-2
        argument-1 
Salomon Zhang
  • 1,553
  • 3
  • 23
  • 41
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
7

This is because the %s format specifier in the format string you pass to printf means that the corresponding argument should be a string, not a single character. And in C, a string is a pointer to the beginning of a block of characters that has a null character (byte with a value of 0) at the end.

Basically, this works because you're doing exactly what you're supposed to in order to print a string.

Eric Finn
  • 8,629
  • 3
  • 33
  • 42
2

The %s formatter to printf expects a "string", which is really a pointer to a null-terminated array of characters.

That is to say, printf expects you to pass the pointer to it. When you dereference the pointer, it's taking the letter J, whose value in ascii is 74 (decimal), and tries treating that as a pointer to an array. That's an area of memory that's inaccessible, so you get the segmentation violation.

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
1

The format specifier %s tells printf to expect a pointer to a null-terminated char array. Which is what name and ptr are.

*name and *ptr are not. If you dereference them, you'll get back a single char, which is basically lying to printf - resulting in undefined behavior.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

*ptr is essentially a reference to a single char, not to the string of char's. due to this char * and char[] are essentially the same thing

bizzehdee
  • 20,289
  • 11
  • 46
  • 76
0

When you declare char prt = name thats where you are dereferencing it. the "" here isn't part of the variable just a way to show you want what that variable points to. If you were to put the *prt again in your printf you are doing it twice. name is an array of characters and *ptr is a dereferenced pointer to those characters.

Hope that explaination helps :-)

Sothwick80
  • 88
  • 5