0

I'm confused in understanding how pointers to char work.

What is the difference between using char *s = "car"; and s = "India";?

And what about char **s?

How will these be stored?

anastaciu
  • 23,467
  • 7
  • 28
  • 53
Lavitha K
  • 39
  • 4
  • 2
    Please read https://www.geeksforgeeks.org/whats-difference-between-char-s-and-char-s-in-c/ and https://www.geeksforgeeks.org/storage-for-strings-in-c/ . Strings are character array in c so character pointer just keep the base address (offset) – SayAz Apr 10 '20 at 14:37
  • **s , this one is double pointer, used to keep address of pointer. must read https://www.geeksforgeeks.org/double-pointer-pointer-pointer-c/ – SayAz Apr 10 '20 at 14:38
  • I think this is a valid question, why is this question closed? – aldok Jan 26 '22 at 16:02

3 Answers3

1

1st case

char* s = "car";

In this case you declaring a char pointer and at the same time assigning it a string literal, in other words, making it point to the beginning of the string literal.

2nd case

char* s;
//some code;
s = "india";

This is the same as first, the difference is that you are first declaring the pointer, and later assigning it the string literal.

3rd case

char** s;

Is a pointer to a pointer to char or double pointer to char, take this sample:

#include <stdio.h>

int main()
{
   char* ptr1 = "abc";
   char** ptr2;
   ptr2 = &ptr1;
   printf("%s", *ptr2);
}

Thhis means that ptr2 is pointing to ptr1 pointer to char (so it's a pointer to pointer to char), through indirection ptr2 can be used to access the beggining of the string pointed by ptr1.

Output

abc

Where the string literal is stored varies deppending on the platform, this answer has some details, as does the link I provided for string literal documentation.

String literals are not modifiable (and in fact may be placed in read-only memory such as .rodata). If a program attempts to modify the static array formed by a string literal, the behavior is undefined.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
1

String literals like "car" and "India" are stored in arrays of character type such that they are available over the lifetime of the program. Under most circumstances, when an expression of array type appears in the code, it is implicitly converted ("decays") to an expression of pointer type, and the value of the expression is the address of the first element of the array.

So suppose our "car" string is stored as an array of char starting at address 0x8000:

         +---+
0x8000:  |'c'|
         +---+
0x8001:  |'a'|
         +---+
0x8002:  |'r'|
         +---+
0x8003:  | 0 |
         +---+

When you write

char *s = "car";

the expression "car" is converted from type "4-element array of char" to "pointer to char", and the value of the expression is the address of the first element - 0x8000. So, that 0x8000 address is written to s1:

   +--------+
s: | 0x8000 |
   +--------+

Later on, when you write

s = "India";

the address of the first element of the array that stores "India" is written to s.

Here's a practical example. I've written a small utility that prints out the addresses and contents of multiple variables. Here's the code:

#include <stdio.h>
#include "dumper.h"

int main( void )
{
  char *s = "car";

  char *names[] = { "s", "\"car\"", "\"India\"" };
  void *addrs[] = { &s, "car", "India" };
  size_t sizes[] = { sizeof s, sizeof "car", sizeof "India" };

  dumper( names, addrs, sizes, 3, stdout );

  s = "India";

  dumper( names, addrs, sizes, 3, stdout );

  return 0;
}

Here's how it looks on my system - first we look at the strings themselves:

      "car"     0x104f2ff71   63   61   72   00    car.

    "India"     0x104f2ff88   49   6e   64   69    Indi
                0x104f2ff8c   61   00   00   00    a...

The string "car" is stored starting at address 0x104f2ff71, and the string "India" is stored starting at address 0x104f2ff88.

Now we look at s:

          s  0x7ffeeacd0a10   71   ff   f2   04    q...
             0x7ffeeacd0a14   01   00   00   00    ....

s is stored starting at address 0x7ffeeacd0a10, and it's contents are the address of the string literal "car". Since x86 is little-endian, multi-byte values have to be read right-to-left.

After we write

s = "India";

our memory looks like this:

          s  0x7ffeeacd0a10   88   ff   f2   04    ....
             0x7ffeeacd0a14   01   00   00   00    ....

Now s is storing the address of the array containing "India".

what is char **s? How it will be stored?

You can have pointers to pointers:

char **s2 = &s;

s2 just stores the address of the variable s. Pointers to pointers come up when you're dealing with arrays of pointers, or when you're passing a pointer to a function and you want the function to be able to write a new pointer value.

Different pointer types may have different representations - the only guarantees are:

  • char * and void * have the same representation and alignment;
  • pointers to qualified types have the same representation and alignment as pointers to the corresponding unqualified type (i.e., int * and const int * are stored the same way);
  • All struct pointer types have the same representation and alignment;
  • All union pointer types have the same representation and alignment;

So it's possible for a char ** object to be stored differently from a char * object. On most modern systems like x86, all pointer types are stored the same way, but there are oddballs out there where that's not the case.


  1. In a declaration, the * operator is simply part of the type; it is not dereferencing anything. We're storing the value to s, not to what s points to.

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

char *s = "car"; and s = "India"; are the same thing except for the fact that char *s = "car"; defines (creates) a new s variable which didn't exist before, while s = "India"; reuses the existing s. In both cases s is a variable pointer to the first character of the string which is created in a non writable part of the data space. i.e. You can change s to another string (e.g. set it to "India" or increment it), but you cannot change the pointed memory (e.g. you can't do s[0]='e').

char **p; just defines a pointer to a pointer (to a string), so you could write p=&s; and if you then wrote *p="Terminator"; s would now point to a new "terminator" string.

There is another case that you should compare with the first two, which is char s[20] = "Hello"; In this case, s is not a variable but a constant pointer to a variable 20 bytes space, in which you have stored "Hello\0". In this case, you CANNOT point s to another string as in s="turlututu";, but you can change the content of the 20 bytes space, providing you do not overflow outside this space and keep the content properly terminated with a '\0' (not terminating your string is not a syntax error, but it is a dangerous practice).

Camion
  • 1,264
  • 9
  • 22