Jump to content

C Language: Pointers doubt 01?

- - - - -

  • Please log in to reply
9 replies to this topic

#1
gautham

gautham

    Learning Programmer

  • Members
  • PipPipPip
  • 33 posts
#include<stdio.h>


void main()

{


char *ptr, k='p';


ptr=&k;


printf("%c",*ptr);



char* cp;

char c[9]={"adsf"};


cp=&c[0];


//printf("%s",*cp); <-- it is showing general protection error


}


=====

What is wrong with the above statement, when i am executing "printf("%s",*cp);"<-- it is showing general protection error

Friends, in the above program why

1. printf("%c",*ptr);

2. printf("%s",*cp);


Why 1. is working and not 2.?

3. printf("\n%s",*(&cp)); <-- this is also working.


#2
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
cp is a pointer.

Should be:

printf("%s", cp);


Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#3
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
3 attempts to treat the contents of the pointer as a string (it's not, it's an address), instead of print the string it points to.

*cp is the same as c is the same as &c[0], any of which would be valid.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#4
gautham

gautham

    Learning Programmer

  • Members
  • PipPipPip
  • 33 posts
@WingedPanther


I am little bit confused, can you or anyone explain in detail about basic concept of pointers and strings...


when the following statement is working:

3. printf("\n%s",*(&cp)); <-- this is also working.


*cp is supposed to display the value contained in the Address which is holding by cp.


*(&cp) isn't it same as *cp?


Thank you.

#5
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others
Let me add comments to the code to help explain what's happening.

#include<stdio.h>

void main()
{

char *ptr, k='p'; 
//this creates two variables: 
//ptr, which accepts the address of a char as its contents, is unitialized, and is located someplace (let's say at 0x1234000A)
//k, which accepts a char as its contents, is initialized to 'p', and is located someplace (let's say at 0x1234000C)

ptr=&k;
//This updates the contents of ptr to the address of k, 0x1234000C

printf("%c",*ptr);
//*ptr is the variable located at 0x1234000C, or k, and it's contents, 'p', are printed


char* cp;
//this creates another variable, cp, which accepts the address of a char, is unitialized, and is located someplace (let's say at 0x1234000D)
char c[9]={"adsf"};
//this creates an array of 9 chars with the following information:
//c[0] accepts a char, is initialized to 'a', and is located someplace (let's say at 0x1234000F)
//c[1] accepts a char, is initialized to 'd', and is located someplace (let's say at 0x12340010)
//c[2] accepts a char, is initialized to 's', and is located someplace (let's say at 0x12340011)
//c[3] accepts a char, is initialized to 'f', and is located someplace (let's say at 0x12340012)
//c[4] accepts a char, is initialized to '\0', and is located someplace (let's say at 0x12340013)
//c[5] accepts a char, is initialized to '\0', and is located someplace (let's say at 0x12340014)
//c[6] accepts a char, is initialized to '\0', and is located someplace (let's say at 0x12340015)
//c[7] accepts a char, is initialized to '\0', and is located someplace (let's say at 0x12340016)
//c[8] accepts a char, is initialized to '\0', and is located someplace (let's say at 0x12340017)
//c is treated as a pointer to c[0], that is, it returns 0x1234000F

cp=&c[0];
//cp is set to 0x1234000F
//printf("%s",*cp); <-- it is showing general protection error
//this would throw an error, because you dereference cp and attempt to print the string located in memory located at the address of the integer representation of character 'a'.  Usually, this is OUTSIDE YOUR PROGRAM, and probably inside OS memory, which is protected.
printf("%s", cp); //this is equivalent to printf("%s", c);
}

Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#6
gautham

gautham

    Learning Programmer

  • Members
  • PipPipPip
  • 33 posts
@WingedPanther

Thank you for your help so far, appreciated, i understood what you have said so far, but i have few more doubts:


cp=&c[0];

1. When we are assigning the address of "c[0]" to cp, how come it is displaying the entire string, since c[0] contains only one char which is 'a'?


printf("%s", cp); //this is equivalent to printf("%s", c);

2. so "%s" forces the variable "cp" to print the string attached to c[0] and the rest?



regards.

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,254 posts
  • Location:C:\Countries\US

gautham said:

1. When we are assigning the address of "c[0]" to cp, how come it is displaying the entire string, since c[0] contains only one char which is 'a'?

The thing is, the computer doesn't look at the size of whatever's at c[0], even though C does. The computer doesn't even care, you just pass the memory address to it, and it displays everything at and after that address; it doesn't have a way of knowing otherwise.

gautham said:

2. so "%s" forces the variable "cp" to print the string attached to c[0] and the rest?

The thing is, in both cases you pass the same value for parameter 2. Again, the compiler sees them as different, but the computer knows no better, because both evaluate to the same memory address.

When you use an array ('c' , in this case, is an array of characters) without specifying the index (the part in [noparse][brackets][/noparse]), C treats it as the memory address of the array, and not the actual contents of the array.

And since 'cp' is the pointer to (the memory address of) the character array, both 'cp' and 'c' - as they are referred to in the code you provided - translate to the same value, and the computer can't tell the difference.

As for the "%s" , the 's' tells printf () that the corresponding parameter (in this case 'cp' or 'c') is a memory address of an array of characters. Because of that, printf () displays all the characters in that array, stopping at the character 0 (NULL, not '0'). This also relates to the above, as you said, why does it output the whole string, and not just that character; that's because all printf () knows is the memory address of the character, it doesn't know that it should stop after printing 1 character, so it continues on, until it reaches that '\0' .

#8
gautham

gautham

    Learning Programmer

  • Members
  • PipPipPip
  • 33 posts
@RhetoricalRuvim

Thank you for the answer.


What is the graphical representation of char c[9]={"adsf"}; that happens inside the memory?






-------------------------------------------------------
a <------> s <------> d <------> f <------> '\0'
-------------------------------------------------------
8679 8680 8681 8682 8683


or



----------
8679 <-- address of c[9] array
----------
2968

c <-- variable


#9
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,254 posts
  • Location:C:\Countries\US
If I understood your question right, it's the latter.

So 8679 would be the address of the array, and the array would actually be the side-by-side blocks (in this case bytes).

Memory Map (by byte): 

address   | value 

8679              'a' 

8680              'd' 

8681              's' 

8682              'f' 

8683              0 

8684              0 

8685              0 

[I]... and so on, until it fills 9 bytes...[/I] 

Then, when you say something like this:
printf ("%s", c); 
, the compiler translates that to something like this (this is code that is based on what the computer's processor is used to reading):
lea eax, [ebp-9] 

push dword eax 

push dword ?_001 

call printf 

add esp, 8 
; and, later on,
?_001: 

db "%s", 0 

So it loads the address of c, and passes it as the second parameter. Then it passes the address of the "%s" string (array of characters), as the first parameter (the computer's processor actually does have to pass parameters in backwards order). After that, it calls the printf () function, after what - because of the way the C calling convention works - it cleans up the stack by "undoing" the two PUSH instructions it did before the call.


I hope this helps. :)

#10
gautham

gautham

    Learning Programmer

  • Members
  • PipPipPip
  • 33 posts
@RhetoricalRuvim


Thank you for the answer, Appreciated


regards.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users