12

I would like to understand how pointers work, so i created this small program. first of all i create a p pointer, which points to a char.

The first question is at this point. If i create a pointer, the value of it is a memoryaddress (if i point it to a non-pointer object), but this time it is "haha" in my example. Why does it work this way in char*? And how i can add value to it with cin >> p?

My second question is that, i created a q char, which has the value of the *p pointer at the point i created it. BUT its value and address are "h" too, but why? It must be the memory address of this char object! It's pointless :D (mingw - gcc)

#include <iostream>

int main() 
{
 /* char *p;
    cin >> p;                      //forexample: haha */

    char * p = "haha";
    char q = *p;
    std::cout << "&q = " << &q << std::endl;   //&q = h
    std::cout << "q  = " <<  q << std::endl;   //q = h

    return 0;
}

MORE: If i allocate memory first with char a[100]; char *p=a; then &q = h»ŢĹ, so "h" and some mess. but it should be a memoryaddress! and my question is, why is not it address then?

SuperWill
  • 9
  • 5
Iburidu
  • 410
  • 2
  • 5
  • 15

5 Answers5

11

Think of char* p; as of address in memory. You did not initialize this pointer so it does not point to anything, you cannot use it.

To be safe always:
either initialize pointer to zero:

char *p = 0; // nullptr in C++11

or initialize to some automatic

void foo() {
  char a[100];
  char *p = a;
}

or global memory:

char a[100];
void foo() {
  char *p = a;
}

or get dynamic memory:

char* p = new char [100];

Then you can use p (if not NULL) to read data and to read from p...


For your misunderstaning of operator >> (std::istream&, char* p). This operator expects that p points to some memory (automatic,global,dynamic - no matter) - it does not allocate memory by itself. It just reads characters from input stream until whitespace and copy it to the memory pointed by p - but p must already points to some memory.


For taking address of char q;. Of course you can take address of q: &q, and it type is char* p. But &q is different that p, and this q=*p just copies first character pointed by p to q, it cannot change address of q - its address is unchangeable. For cout << &q - operator << (ostream&, char* p) expects that p points to NULL terminated string - and &q points to memory containing "H" but what is after this character no one knows - so you will get some garbage on screen. Use cout << q to print single character.

Magnus Hoff
  • 20,105
  • 8
  • 58
  • 81
PiotrNycz
  • 20,687
  • 7
  • 55
  • 102
  • so, you said cin does not allocate memory, so where is my "haha"? how can a pointer contain a whole string? q is a simple char variable, so it can contain any character of p, and i haven't got my "haha" text allocated, so that's why my "h" doesnt have memory address to? it is clear, but i have a question then: when i copy the character to q (char q = *p), it is NOT COPYING really, its just pointing to that data, which isn't allocated? so the problem is everywhere that, my haha text is not allocated, so i can't have any addresses from that? – Iburidu Oct 13 '12 at 22:35
  • ok, i created a program with int, and int has been allocated, i can cout << p; and it will write the address back. the program is short and simple: " int a[10]; int *p = a; cin >> (char *)p; cout << p << "," << atoi((char*)p); " – Iburidu Oct 13 '12 at 22:59
  • 2
    Because you did not assign to `p` any value even `0` - then it points to some random address. You copied "haha" to some random memory in your program - it could cause anything, it is undefined behavior - it can even cause sending an e-mail to your boss that you have better job - but it can also happen that this random memory is not used - so it seems like your program is working correctly. – PiotrNycz Oct 13 '12 at 23:00
  • For you last example: `int a[10];` - let say memory address of `a` is 0x123. `int p = a;` - you cast address to int - so `p == 0x123` as value. `(char*)p` reverse casting - so your program thinks 0x123 is the beginnig of char array. So `int[10]` is equivalent to `char[10*sizeof(int)]`... So you have memory, everything is OK. – PiotrNycz Oct 13 '12 at 23:06
  • yes, but in my example p equals to a memory address. and i created your example with a[100], and p was "haha", was not equal to a memory address, but it should be! – Iburidu Oct 13 '12 at 23:12
  • Consider: `char a[100]; char *p = a; strcpy(p, "HA HA");` `p` is not equal to address of string literal `"HA HA"` (p != "HA HA") - it is still equal to `a` `(p == a)`. But `strcmpy(p, "HA HA") == 0` which means characters were copied from `"HA HA"` to `a[100]` with `p` as `a` address representation. – PiotrNycz Oct 13 '12 at 23:17
  • then p should be &a[0] and not "haha"! – Iburidu Oct 13 '12 at 23:22
  • `p==a` or `p==&a[0]` because `a == &a[0]`. And (*p == 'H') and `(a[0] == 'H')` – PiotrNycz Oct 13 '12 at 23:24
  • yes, but p != "haha", and IT IS "haha", and lol! &a[0] is haha too. how can &a[0]=="haha" ? – Iburidu Oct 13 '12 at 23:33
3

First thing to learn and always remember about pointers is to make sure to allocate memory for them, otherwise your program won't run properly.

Your code should actually be modified as follows to allocate memory so that "cin" can write the user input into the allocated memory:

int main() {
    char *p = new char[1024];      // allocate memory so cin
    cin >> p;                      //forexample: haha
    char q = *p;
    cout << "&q = " << &q << endl; 
    cout << "q = " << q << endl;   
    return 0;
}

Now, a character pointer is a variable pointing to a position in memory holding a set of characters (not necessarily one character, maybe more than one, maybe none as in the case of the special value null), while a character variable is actually holding a single character (not a set of characters).

The basic operators when dealing with pointers is the &(address of) and *(value at). The & retrieves the address of a variable, so if we have [char q;] then [&q] would be a character pointer. On the other hand, the * retrieves the value at the given pointer, so if we have [char *p;] then [*p] would be the character in memory at which p is pointing.

Now back to your example, comments inline for illustration

int main() {
    // allocate a place of 1024 character in memory
    // and let p points to that place
    char *p = new char[1024];      

    // call cin to read input from the user and save
    // it in memory at the location pointed to by p
    // NOTE: cin would put an extra NULL character 
    // at the end to terminate the string
    cin >> p;                      //forexample: haha

    // Now p would be pointing to a piece of memory like this
    // [h] [a] [h] [a] [\0]

    // use the value at operator to de-reference the pointer
    // p, the result would be a single character which 
    // will be the first character in memory p is pointing at
    char q = *p;

    // printing the value of (the address of q)
    // Note you have a problem here as cout will
    // be handling the memory starting at the address 
    // of q as a string while it is not, so you
    // will get a string starting with "h" and followed
    // by whatever is there in memory by the time of execution
    cout << "&q = " << &q << endl;

    // printing the value of the character q
    cout << "q = " << q << endl; 
    return 0;
}

I hope it helps

Hisham
  • 422
  • 3
  • 7
  • yes, it's clear, if i allocate place to p, then it will write "h and some mess" to &q, but if i dont allocate place to p, then it writes "h" only, what is the same as *p. so q=&q? :D but i think PiotrNycz was right and it is because "haha" was not allocated, so it hasn't got memory address, so &q (which is p), can't point to anywhere, but why it stopped after "h" then? – Iburidu Oct 13 '12 at 22:46
  • 1
    @Iburidu the specific case happening on your machine/compiler is not the general case. The outcome of storing data in un-allocated memory space is unpredictable. In your case, the memory was already full of zeroes, so printing the string starting &q printed out "h" properly just by mere chance, nothing more. – Hisham Oct 14 '12 at 11:10
  • ok, i allocated by adding char a[100]; int* p=a; BUT why p == "haha", if it should be a memory address (&a[0])? – Iburidu Oct 14 '12 at 13:00
  • @Iburidu arrays in C++ are implemented as pointers, so most of the time you can use arrays and pointers interchangeably. For example: int *p = new int[100]; then you can do p[0]=1; p[1]=50; ... etc. – Hisham Oct 14 '12 at 16:57
  • @Iburidu Back to your example: cout will print out the string "haha" because it will notice you are trying to print a char* ... if you want to print the address, you may cast it to `(void *)` or use the statement `printf("%p", p);` – Hisham Oct 14 '12 at 17:08
1

You should have something like:

#include <iostream>
using namespace std;

at the top of your program. Or could omit the using and refer to std::cin and std::cout.

int main() {
    char *p;

p is a pointer, but you haven't initialized it, so it could point anywhere or nowhere. You need to initialize it, for example with:

p = new char[100];

...

    cin >> p;                      //forexample: haha

This is ok if you've initialized p to point somewhere -- except that you can overflow the buffer it points to if you enter too much data. That's ok for a simple test program like this, but in practice you'll want to take measures to avoid it.

    char q = *p;
    cout << "&q = " << &q << endl; //&q = h

&q is of type char*, a pointer to char. Sending a char* value to cout doesn't print the value of the pointer (a memory address); it prints the string that it points to. (Though I'm getting some odd results when I run it myself; I may be missing something.) If you want to see the pointer value, cast it to void*:

count << "&q = " << (void*)&q << endl;

(Or you could use one of the C++-specific casts; I'm not sure which is best.)

    cout << "q = " << q << endl;   //q = h

Here q is just a char, so this prints its value as a character: h.

    return 0;
}
Keith Thompson
  • 230,326
  • 38
  • 368
  • 578
  • yes, on my code i took those first two lines, but its obvious, so i havent put here. i understand it, but cout << &q must be cout << p then, right? and its not. &q = "h" and p = "haha" – Iburidu Oct 13 '12 at 22:40
0

the string literate will be stored in .rdata section which will be read only so reading into it with std cin would crash the program

the second thing , when you write this :

char *p = "some text";

then the pointer p points to an allocated and read only memory , as the rdata section will be surely allocated and prepared by the windows loader , but as I said .rdata can't be modified

then when you write this :

char q = *p;

you only assign q to the first char in p as * returns the value the pointer is currently pointing to so if you tried this :

++p;
q = *p;

the q will hold 'a' not 'h' as the pointer is an address that points to a some chars beginning from the first so increasing by one it will make the pointer point to the second char and q will hold this value

dev65
  • 1,011
  • 4
  • 17
0

Better way to do it is:

    int arraySize;
    cin>>arraySize;
    char *a=new char[arraySize];
    cin >> a;
Nagendra Reddy
  • 461
  • 5
  • 6