Do pointers only hold addresses to other variables? - c++

I am a bit confused when it comes to pointers.
Some sample code:
char str1[80];
char *p1;
cout <<"Enter a string"<<endl;
cin >> str1;
p1 = str1;
On the the last line of code, if str1 contains 'Test', how come p1 now contains 'Test'. Isn't p1 still a pointer? I thought pointers only contain addresses to other variables.

p1 doesn't contain Test. It contains the address of a byte in memory that is set to the ASCII value of the character T, followed by e, s, t, and a 0. That address is the address of the array str1, an 80 char array.
If you try to print str1 or p1, you'll get the output Test. This is because you cannot pass arrays to functions, so if you try to, the array name will decay into a pointer to the first element, just like p1. So str1 will decay to a pointer to the T and p1 is already a pointer to the T so you get the same output when printing either because they both point to the same address in memory.

p1 is a pointer.
That means that p1 contains the memory address of the first character of str1.
When you went to see what p1 "held", you probably did something like cout << p1, or cout << p1[3]. Either one of these will dereference p1, treating it as a pointer-to-array-of-characters.
To see the actual value of p1, try cout << (void*)p1. This will be the same as the actual value of str1 - a memory location which contains 'T', if you entered "Test".

Pointers hold address, nothing more. Sometimes you dereference pointers to get the data, other times you pass the pointer around to code that will dereference it.
For example :
p1 = 0; //Point to invalid memory address, but an address nonetheless
p1 = str1 //Point to a valid buffer. p1 now holds an new address, nothing else
if(*p1 == 'A') //Dereference the pointer (gives a character)
printf("The first character in str1 is A.\n");
You can emphasis the fact that p1 does not hold data other than the pointer by reorganizing your program like this :
char str1[80];
char *p1;
p1 = str1; //Point to un-initialized memory, your compiler might complain.
//but p1 is happy. It holds an address, it will never "hold" anything else.
//*p1 is valid (will not crash) but holds random garbage, do not use it!
cout <<"Enter a string"<<endl;
cin >> str1; //Now str1 was initialized
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("The first character in str1 is A.\n");
Now to emphasis the fact that p1 and str1 are the same thing (the same address in memory), add this to the program :
str1[0] = 'A'; //Put a capital A in str1
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("Now that we forced an A, this test is always true.\n");

What told you that p1 wasn't a pointer?
Functions and operators like cout::<< and printf are designed to print strings (as well as other data types) so they will appropriately dereference pointer arguments for you: give it a pointer to a string and it will print the string at that address. If you really want it to print the value of the pointer as an address, you have to cast it with (void *).

Do remember that, for array:
int array[N];
The usage of array would essentially mean &array[0], and therefore, following are same:
PrintAddress(&array[0]); // void PrintAddress(int*);
PrintAddress(array);
This way, when you do:
int *pAddress;
pAddress = &array[0];
PrintAddress(pAddress);
You can modify second line as:
pAddress = array;
And, just for completeness, following are same:
PrintAddress(&array[2]);
PrintAddress(array+2);
And so the following:
pAddress = array+5;
pAddress = &array[5];

printf("Address: %p\n", (void *)p1);
will print the address (from how to see address of a structure in printf).
printf("String: %s\n", p1);
will print the string.
The first is the actual content of p1, the second is what this content means in the context of your program: p1 is a pointer to char, which is the usual way in C to represent strings (ending with a 0 - '\0').

Related

how does this while loop sort out pointers?

I am a complete novice to pointers and discovered them about a week ago. This book I am reading introduced me a problem for me to solve and it took me a while without coming up with the correct solution, and so I cheated. Looked it up and came up with this:
#include <iostream>
void mystrcpy(char* str1, char* str2) {
while (*str1++ = *str2++);
}
int main() {
char str1[15] = "C++";
char str2[15] = "Pointers";
std::cout << str1 << std::endl << str2 << std::endl;
mystrcpy(str1, str2);
std::cout << str1 << std::endl << str2 << std::endl;
}
Question was me to fill in the blanks at the void function to solve the problem and the problem beneath at main() which printed out this:
C++
Pointers
C++
Pointers
and it wanted me to look like this:
C++
Pointers
Pointers
Pointers
So, basically I do not understand how while (*str1++ = *str2++); solves this? Been looking at it for a while still clueless how it sorst the strings out to output it like that
Pointers are like variables that point to a specific location in memory. You can dereference them to get the value that they point to with *str2, and increment them to make them point to the next value in memory (based on their datatype): str2++.
The precedence can be confusing. *str2++ works in this order:
get the value pointed to by str2, and then
increment str2 to point to the next character
while (*str1++ = *str2++);
This statement copies each char from str2 into str1 until it reaches a null pointer in str2. It works by:
*str2: get the character pointed to by str2
*str1 = *str2: write the character pointed to by str2 to the destination pointed to by str1
str1++, str2++: increment str1 and str2 for the next loop iteration. Now each pointer points to the next character in each string.
When str2 points to a null terminator, *str2 returns 0 (or '\0'), and *str1 = *str2 will write it to str1, and also return the 0 which will cause the while loop to complete.
str1 starts as C++, and str2 starts as Pointers. Then the mystrcopy function is called which copies the value of str2 into str1.
The copying is done by the line in question:
while (*str1++ = *str2++);
I agree that this line is relatively opaque, but here are some basics:
The * on each "de-references` each pointer. That means it is looking at the value stored at the given address, not the address itself.
The ++ is used to shift the pointer address from its current location to the next location in the array. It is placed after the pointer so that the pointer is incremented after we get/set it's value.
The while-loop here has only a condition, however the condition itself is an action. The action is executesd and the result is checked. When the end of the string is reached, the \0 char is found which terminates the loop.
So, in summary, the line copies a single char value from str2 into the value of str1, increments both pointers to point to the next char of each, then repeats until failure.
It is worth noting that, although the pointers are being changed within the function to point at new addresses, not just the start of each array, these pointer variables are not passed into the function by reference, and so the pointer variables outside the function remain unchanged, still containing the address of the first char. However, the data stored at those addresses has been modified.
Each iteration, the loop assigns the value of the second element of array to the first element of the array, after which it checks whether the left set value is equal to zero, and if not, the loop continues. At the end of the iteration, the loop increments both variables.

memory leak, pointer to literal

I've learned not to let pointer point to literals because it causes memory leaks. But when I assign a pointer to a literal, it still points to the same address than before:
unsigned maxlen = 20;
char* testpointer = new char[sizeof(char) * maxlen]; //Pointer points to RAM
cout << "&testpointer = " << &testpointer << endl;
strncpy(testpointer, "Happy Eastern", 13);
cout << "&testpointer = " << &testpointer << endl;
testpointer = "Merry Christmas"; // I know I shouldn't do this
cout << "&testpointer = " << &testpointer << endl;
I still get the same memory address each time:
&testpointer = 0x28fc60
&testpointer = 0x28fc60
&testpointer = 0x28fc60
Shouldn't the address change when I let the pointer point to a literal?
I thought the memory which I allocated with new should be in RAM while the literal should be in ROM, which should have a different address. Am I wrong?
Thank you, Philipp
Your cout instructions are printing the address of the variable called testpointer. That's some location in the stack frame of the current function. It has nothing to do with the value of testpointer, nor with the value pointed by testpointer.
Also, either whoever told you that you should not let a pointer point to a literal was mad, or you did not understand what they said to you. There is absolutely no problem with letting a pointer point to a literal.
&testpointer is a pointer to the variable testpointer. It's where the variable itself is stored.
If you want to print where testpointer is pointing, you print its value (as a void* since otherwise operator<< will print it as a string):
std::cout << "testpointer = " << static_cast<void*>(testpointer) << '\n';
Also note that on modern computers there's really no ROM. The executable image is loaded from the disk into the virtual memory ("RAM") and that includes data such as constant string literals (which are really arrays of constant characters).
Also, you can have pointers to constant string literals, but they should really be pointers to const char since constant string literals are constant. The problem is with the reassignment of the variable. You would get the same problem with e.g.
unsigned maxlen = 20;
char* testpointer = new char[sizeof(char) * maxlen];
// ... stuff happens...
testpointer = new char[some_other_size];
If there's no delete[] before the second new[], then you have a memory leak.
Finally a warning about your use of std::strncpy: It will not add the terminating '\0' at the end. That's because your supplied size (the third argument) is smaller or equal to the length of the source string, in which case the function will not add the terminator. So don't attempt to print the contents of the "string" or use it as a "string".
There's two misconceptions in your question.
One, you're printing the address of testpointer instead of its value, so it's obviously not changing. If you replace &testpointer with static_cast<void*>(testpointer), you will see the difference. Note that the cast is necessary, because << is overloaded for char* to print the characters instead of the pointer itself.
Two,
not to let pointer point to literals because it causes memory leaks
is simply not true. A leak happens if and only if you have some dynamically allocated memory and lose any reference to that memory; in other words, if you no longer have a pointer to that memory. In such case, you no longer have a way to deallocate that memory, and hence you leak it.
This happens in your program by doing this sequence of operations:
char* testpointer = new char[sizeof(char) * maxlen];
testpointer = "Merry Christmas";
Either one of them is fine on its own(1), but together, they cause a leak:
First, you allocate memory
Then, you forget its address (by pointing the pointer elsewhere).
Note that a literal being involved is irrelevant. This would be exactly the same leak:
char* testpointer = new char[sizeof(char) * maxlen];
testpointer = nullptr;
As would this:
char* testpointer = new char[sizeof(char) * maxlen];
testpointer = new char[sizeof(char) * maxlen];
(1) Except you're pointing a char * at a string literal, which is not allowed since C++11, because string literals are const. You'd need a const char * for that.
I've learned not to let pointer point to literals because it causes memory leaks.
Pointing to string literals does not cause memory leaks. It's fine to point to a string literal.
Incidentally, your program does leak memory.
But when I assign a pointer to a literal
Your program does not assign the pointer after initialization.
it still points to the same address than before:
You don't stream the address that the pointer points at. You use addressof operator on the pointer variable, so you stream the address where the pointer is stored. This wouldn't change even if you did assign the pointer.
Shouldn't the address change when I let the pointer point to a literal?
The address of the pointer variable wouldn't change. But the address it points to (i.e. the value of the pointer) would change. But you neither point to a string literal, nor do you observe the address that is pointed at.

C++ char pointer

Why does the following happen?
char str[10]="Pointers";
char *ptr=str;
cout << str << "\n"; // Output : Pointers
int abc[2] = {0,1 };
int *ptr1 = abc;
cout <<ptr1 << "\n"; // But here the output is an address.
// Why are the two outputs different?
As others have said, the reason for the empty space is because you asked it to print out str[3], which contains a space character.
Your second question seems to be asking why there's a difference between printing a char* (it prints the string) and int* (it just prints the address). char* is treated as a special case, it's assumed to represent a C-style string; it prints all the characters starting at that address until a trailing null byte.
Other types of pointers might not be part of an array, and even if they were there's no way to know how long the array is, because there's no standard terminator. Since there's nothing better to do for them, printing them just prints the address value.
1) because str[3] is a space so char * ptr = str+3 points to a space character
2) The << operator is overloaded, the implementation is called depending on argument type:
a pointer to an int (int*) uses the default pointer implementation and outputs the formatted address
a pointer to a char (char*) is specialized, output is formated as a null terminated string from the value it points to. If you want to output the adress, you must cast it to void*
The empty space is actually Space character after "LAB". You print the space character between "LAB" and "No 5".
Your second question: You see address, because ptr1 is actually address (pointer):
int *ptr1;
If you want to see it's first member (0), you should print *ptr1

c++ pointers and string of characters

am a bit confused about something in string of characters and pointers regarding c++ language ..
well, i came to know that a name of an array of characters is actually the address of it's first element and i also know that The cout object assumes that the address of a char is the address of a string, so it prints the character at that address and then continues printing characters until it runs into the null character (\0).
but here is the interesting part i tried this code in codeblocks
char arr[10]="bear";
cout <<&arr<<endl; // trying to find the address of the whole string
cout<<(int *)arr<<endl; // another way of finding the address of the string
cout<<(int *)arr[0]<<endl; // trying to find the address of the first element
what came on the screen was as follows
0x22fef6,
0x22fef6,
(0x62) <<<< My question is , what the heck is that? .. If the arrayname holds the address of the first element , shouldn't the first element address be " 0x22fef6 " ???????????????????
The [] operator does not return an address but dereferences the pointer at the given offset.
You could write an equivalent to the [] operator as follows:
char arr[10] = "bear";
char c = *(arr+0); // == arr[0] == 'b'
That is, you take the pointer arr, increase it by 0 char and then dereferences it to get it's value.
char arr[10]="bear";
cout <<&arr<<endl;
cout<<(int *)arr<<endl;
cout<<(int *)(arr+0)<<endl; // increases the address by 0
cout<<(int *)(&arr[0])<<endl; // the address of the value at index 0
This would do what you have expected it to do.
arr[0] equals *(arr + 0); you dereference the pointer and obtain the value it holds. To get what you want you need to reference the element, like &arr[0].

Dereferencing a char pointer in C/C++?

I am working in a program using the DWARF and ELF info. I am hooked to another program using a tool called Pin. I have the addresses from the global variables declared in "Y" program and I hook it into my Pin module which I will call "X".
I am getting a bunch of addresses for these global variables. Unfortunately I am having troubles when I try to dereference them. For example (right now I am doing things manually to see if it is doing what is supposed to be doing):
char * limit, * address1;
for(address1 = (char *) 0x804A040, limit = address1 + bytesize; address1 < limit; address1++)
cout << *(address1) << "\n";
I should be getting the variable that is stored in that address which is a char * to a word. Do I have to dereference two pointers in this case? The address and then the char * stored in that address?
This works perfectly fine when I want to dereference an int variable, but whenever I try to dereference a char pointer or variable I get non-ASCII values...
Think like this: if you want to dereference an int, you use int *:
int *addr = (int *)0x12345678;
printf("%d\n", *addr);
But a string is already a pointer, so if you do this:
char *addr = (char *)0x12345678;
You don't need to dereference it to print it out, so you get it this way:
printf("%s\n", addr);
Additionally, suppose you have this memory:
00000001: 0x12345678
...
12345678: 'A'
12345679: 'B'
1234567A: '\0'
...
Let's access the address 0x00000001 and see what we can do:
unsigned int *addr = (unsigned int *)0x00000001;
Now *addr holds an integer which is the address of the first character of our string. Functions that take a string argument, usually ask for the string address, that is, a pointer to it, so *addr is also the string we should print on cout or printf for example.
// This should print "AB"
printf("%s\n", (char *)(*addr));
Now if you dereference our value (0x12345678), we'd get the string's first character, and only it, as a char. So if you misuse it and dereference it to a char *, printf would try to search for the memory 'A', which is 0x00000041, and would probably get a segmentation fault.
So, the right way to dereference its value, to get the first character would be this:
// This should print "A"
printf("%c\n", (char)(**addr));
So, as a conclusion, if you are still getting non-ASCII values, that's probably an issue with this kind of hierarchy between addresses, and I would recommend you to strictly debug the memory and see if creating a pointer to a pointer is the right path to your string.
Yes, you need to dereference two pointers. First to get the address of the variable that holds the char*, and then to dereference the char*.