6

One thing that always confused me , the character pointer. It's after long four years that I am again lingering into c.

Take for example the mentioned case .Why does char pointer behave in this way ? How can we directly address the contents of the pointee when it points to nothing or is it like char pointer stores stuffs other than addresses !

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
char* charPtr="I cant understand why";
int* intPtr=60;


printf("%d\n", intPtr); //displays 60
printf("%p\n", intPtr); // displays the hex value of 60

printf("%s\n", charPtr); // displays the wh0le string
printf("%p\n", charPtr); // displays the start address of the string
return 0;

}

Next the int pointer , How can it accept the value 60 and where does it get stored ?

leaving aside the char pointer and malloc ,I thought the basic idea of the pointer was to get an address to point to !

why does these cases

 *intptr = 60 ; // should be setting the pointee's value to 60
  intptr = 60 ;  // sets the address

throw compilation error while

  int* intPtr=60;

sneaked in without getting an address ( or is 60 taken as the address ,if so why is this not acceptable not in the former case)of the the pointee !

I guess I am missing something here but hey ! Guess what ? they told me to search in SO !

EDIT : Giving the address pointed to by the char pointer to an int pointer also throws in no error !

int8_t* intPtr= (int8_t*)0x80485c8 ; // works without casting too ! I guess addresses are acceptable.

Dereferencing it will give a value equivalent to the first I of the string .Is this a good practise or there exists any other explanation to this leaving out thier byte bit size allocation such as an int can hold a char and so.. ?

As hmjd pointed out the ' initialisation syntax ' is the problem ! I have no problem writing my own code but trouble arises when modifying someone's code !

user1471
  • 439
  • 3
  • 8
Borrito
  • 357
  • 1
  • 3
  • 6

4 Answers4

6

How can we directly address the contents of the pointee when it points to nothing or is it like char pointer stores stuffs other than addresses !

I think the confusion is the initialisation syntax. This:

char* charPtr="I cant understand why";

does not dereference charPtr. It is equivalent to:

char* charPtr;
charPtr = "I cant understand why";

Both code snippets store the address of the string literal "I cant understand why" to the charPtr. There is no dereferencing of a pointer that points to nothing occurring. A pointer variable, of any type, can store an address only.

This:

int* intPtr=60;

stores an address of 60 in intPtr: no int assignment or deferencing is occuring. No int variable exists at this point. The compiler should have emitted a warning at this line. Any attempt to deference intPtr will most likely cause a crash.

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • I think you are right! He is thinking that "a = b;" means "set the value of the variable a to the value of b". But what it actually means is "set the variable a such that its value is b". If x's value is 2, `x = 3;` tries to set the variable `x` to 3, it doesn't try to set 2 to 3. (The basic concept the OP is missing is lvalues versus rvalues.) – David Schwartz Aug 29 '12 at 09:43
  • @hmjd So char pointer is somewhat different from other pointer atleast in this aspect , is it ? You said that int* intPtr=60; stores an address 60 in intPtr so if I put a valid address and dereference it , will I get the value irrespective of the type ? I think it will be better to update the question . – Borrito Aug 29 '12 at 10:58
  • @Borrito, no. The difference here is the initial value you are assiging. For the `char*`, you are assigning a valid address. For `int*`, you are not. If you `int i = 4; int* intPtr = &i;` then `intPtr` would have the address of `i` and it would be legal to deference `intPtr`. – hmjd Aug 29 '12 at 11:01
4

In C, a string literal like "I can't understand why" is stored as an array of char such that the memory is available over the lifetime of the program (all addresses are pulled out of thin air and are not meant to represent any specific platform or architecture):

Item        Address        0x00  0x01  0x02  0x03
-----       -------        ----  ----  ----  ----
"I..."      0x00080000      'I'   ' '   'c'   'a'
            0x00008004      'n'   '''   't'   ' '
            0x00008008      'u'   'n'   'd'   'e'
            0x0000800C      'r'   's'   't'   'a' 
            0x00008010      'n'   'd'   ' '   'w' 
            0x00008014      'h'   'y'  0x00  0x??

The string literal is also an array expression, and in most contexts an expression of type "N-element array of T" will be converted to type "pointer to T", and its value will be the address of the first element of the array (the exceptions are when the array expression is an operand of the sizeof or unary & operators, or is a string literal being used to initialize an array in a declaration).

So when you write

char* charPtr = "I can't understand why";

you're copying the address of the string literal to charPtr:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
charPtr     0xffbe4000     0x00  0x08  0x00  0x00

Note that if the declaration had been

char str[] = "I can't understand why";

str would have been allocated as an array of char long enough to hold the string, and the contents of the string would have been copied to it:

Item        Address        0x00  0x01  0x02  0x03
-----       -------        ----  ----  ----  ----
str         0xffbe4000      'I'   ' '   'c'   'a'
            0xffbe4004      'n'   '''   't'   ' '
            0xffbe4008      'u'   'n'   'd'   'e'
            0xffbe400C      'r'   's'   't'   'a' 
            0xffbe4010      'n'   'd'   ' '   'w' 
            0xffbe4014      'h'   'y'  0x00  0x??

When you write

int* intPtr = 60;

you're initializing the pointer value with 60, not setting it to point to an anonymous integer with the value 60:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
intPtr      0xffbe4004     0x00  0x00  0x00  0x3C

Address 60 is most likely not a valid address, so attempting to dereference intPtr would most likely lead to undefined behavior.

Had you written something like

int x = 60;
int *intPtr = &x;

then you'd have a situation like this:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
x           0xffbe4004     0x00  0x00  0x00  0x3C
intPtr      0xffbe4008     0xff  0xbe  0x40  0x04

In this case, the value of intPtr is the address of x.

Finally, note that initialization and assignment are not the same thing.

T *x = value;

does not dereference x and assign value to the result; it assigns value directly to x. The type of value is treated as T *. Note that you should be getting warnings on

int *intPtr = 60;

along the lines of "making pointer from integer without cast".

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

When you write :

 char* charPtr = "I can't understand why";

This means that the base address of the string "I can't understand why" is being assigned to

charPtr because the string literal also is a pointer to that string.

It can be viewed as :

the concept of string stored in an char array

This means that , in charPtr the base address of the whole string is being stored .Now this is what you have done in your code .

 char *charPtr="i cant understand why";

Adding to that , if you print statements like :

printf("%c","i cant understand why"[0]);//prints i
printf("%c","i cant understand why"[2]);//prints c

These two printf's justify my concepts that the string "i cant understand why" is itself a pointer to the char array in which the string is being stored.

user1471
  • 439
  • 3
  • 8
kTiwari
  • 1,488
  • 1
  • 14
  • 21
1

Your intPtr is initialized to point to the absolute memory address 60. There is no backing store here.

Since you are not dereferencing the pointer itself, you are never trying to read the address 60 which would probably crash your program depending on the environment.

Instead you are passing the pointer value into printf which takes pretty much anything as arguments and interprets the values as you specify in the format string. In your case it will interpret the address of the pointer instead of the pointer value. The address is 60 so that is displayed. Had you used *intPtr instead it would have probably crashed.

Dervall
  • 5,736
  • 3
  • 25
  • 48