In "void pointers" example in the tutorial on cplusplus.com, I try to compare like following. Why do we still need * in parenthesis? What is happening when no *?
void increase(void* data, int psize) {
if (psize == sizeof(char)) {
char* pchar;
pchar = (char*) data;
cout << "pchar=" << pchar << endl;
cout << "*pchar=" << *pchar << endl;
//++(*pchar); // increases the value pointed to, as expected
++(pchar); // the value pointed to doesn't change
} else if (psize == sizeof(int)) {
int* pint;
pint = (int*) data;
//++(*pint); // increases the value pointed to, as expected
++(pint); // the value pointed to doesn't change
}
}
int main() {
char a = 'x';
int b = 1602;
increase(&a, sizeof(a));
increase(&b, sizeof(b));
cout << a << ", " << b << endl;
return 0;
}
Update after accepting solution) I try to make clear what I didn't get, based on #Cody Gray's answer. The address of pchar is incremented to point to nonsense location. But because variable a in main is coutted instead of pchar, this cout still prints a value that somewhat makes sense (in this example it would be 'x').
The * operator dereferences the pointer.
Therefore, this code:
++(*pint)
increments the value pointed to by pint.
By contrast, this code:
++(pint)
increments the pointer itself, pint. This is why the value pointed to by the pointer doesn't change. You're not changing the value pointed to by the pointer, but rather the value of the pointer itself.
Incrementing a pointer will cause it to point to an entirely different value in memory. In this case, since you only allocated space for a single integer, it will point to a nonsense value.
When you make a cast from pointer to other pointer
char* pchar;
pchar = (char*) data;
you telling to compiler to process this memory as char pointer, in which you could perform pointer arithmetic to this variable. Therefore, you are not working with the value of the pointer just with pointer, that's is a memory address in which you are making the arithmetic.
To work with the value you need to use "*" or access to memory pointer by the char.
Related
I've research for half a day and cannot figure out how to pass a simple char pointer, and modify the value in a function. Most of the solutions say to modify the function to accept a char ** parameter.
I have a function I cannot modify. I need to pass a char pointer to it because this function will give me a new calculated char value. I was told I can pass a pointer to a char array and it will work, but I am unsure how to do it.
Passing char pointer as argument to function
I followed the above post and came up with the following code but it still does not work. When I pass the pointer to the char arr[] it does not change its value. My goal is to pass a char pointer and be able to write to it in another function by passing its reference. Any help is appreciated.
enum STATUS {
OK = 0,
BAD = 1,
};
STATUS func1(char *pData)
{
pData = "Hello World";
cout << pData << endl;
return OK;
}
int main()
{
STATUS ret;
char arr[] = "Example String";
char* pArray = &arr[0];
ret = func1(pArray);
cout << arr << endl;
cout << pArray << endl;
getchar();
return 0;
}
STATUS func1(char *pData)
{
pData = "Hello World";
cout << pData << endl;
return OK;
}
That function is doing a shallow copy (ie. changing the value of the pointer pData and not what it points to). You need to do a deep copy of the new string into the memory pointed to by the pData pointer.
The traditional way to do a deep copy of a string is to use the strcpy() library call. You could also use a loop.
I have a function I cannot modify. I need to pass a char pointer to it because this function will give me a new calculated char value. I was told I can pass a pointer to a char array and it will work, but I am unsure how to do it.
That is not true. Whoever said that is lying to you or they are ignorant of the subject matter.
When you use
pData = "Hello World";
you are modifying where pData points to. However, that change is local to the function. It does not change the data in the calling function. You can use std::strcpy for the change to affect the calling function.
std::strcpy(pData, "Hello World");
You can pass the pointer by reference and change the value of the pointer. That will make the change visible to the calling function.
STATUS func1(char*& pData)
{
pData = "Hello World";
cout << pData << endl;
return OK;
}
However, when you do that, arr and pArray in main will be different. arr will continue to have the same value while pArray will point to a completely different value.
STATUS func1(char *pData)
{
*(pData) = "H";
*(pData+1) = "e";
*(pData+2) = "l";
*(pData+3) = "l";
//... etc ...
cout << pData << endl;
return OK;
}
This is changing the memory the pointer points to, not the pointer itself. It can be done better using the functions in the other answers but this is more explicit. If you're using an IDE that allows single step debugging and memory viewing, you can watch the individual bytes in memory change.
This might lead to pointer over runs if the initial memory buffer isn’t big enough.
Also worth mentioning, is your memory big enough for the function you cannot change? Should you allocate memory like this:
char *ptr = new char[1000];
//etc....
if(ptr) delete ptr;
To create (and delete) a bigger, uninitialised memory buffer?
So i want to point a pointer to a character and then output the address put it outputs this weird thing: t+ a. Any help?
#include <iostream>
using namespace std;
int main() {
char a = 't';
char* p = &a;
cout << p;
return 0;
}
You are printing a char* type, which the cout tries to interpret as a string.
Print the value of the pointer (The address it points to) using:
cout << (void *)p;
-- OR --
cout << static_cast<void *>(p);
The problem is that char * is conventionally not just used as a pointer to a char, but a pointer to a null-terminated C-string instead. cout will then print all the characters pointed to by p until it finds a '\0', so you get to see the t and then it prints invalid memory which is undefined behavior which may crash or print garbage or something else.
The way to fix this is to use void * or maybe const void * instead which is just a pointer with an address but no type information attached. void *p = &a; would be one fix. void *p2 = p; and then using std::cout << p2; would be another. You can also use a cast as shown in the other answer, except you should be using a C++ cast like static_cast<const void*>(p) instead of a C cast like (void *)p because once you get used to them they become easier to read and reason about.
If you want address of the pointer, either cast it to void pointer
std::cout << (void *)p;
or use printf with %p option
printf("%p", p);
Otherwise it will be treated as null terminated string, which it is not.
I am trying to pick up my C++; I have basic understanding of pointers and references; but when it comes to char pointer to array, it seems nothing works for me.
I have a small piece of codes here (omitted include and namespace statements), I have included my questions as comments below:
I have gone through at least 5 other questions on SO to try to understand it; but those answers didn't the answer I expected and to the extent that could help understand the actual issue there.
Could you kindly explain the problems I commented below with a bit of depth from the surface (so please don't dive into it directly)?
int main(){
// 1 this is a char pointer to a char;
char * c = new char;
*c ='A';
cout << c << endl; // this gives me memory address;
cout << *c << endl;// this gives me the value in the memory address;
// 2 this is a char array initialised to value "world";
char d[6] = "world";
cout << d[0] << endl; // this gives me the first element of char array;
// 3 this is char pointer to char array (or array of char pointers)?
char * str = new char[6];
for(int i=0;i<6;i++){ //
str[i]=d[i]; // are we assigning the memory address (not value) of respective elements here?
} // can I just do: *str = "world"; what's the difference between initialising with value
// and declaring the pointer and then assign value?
char * strr = "morning";
char b[6] = "hello";
cout << b << endl;
cout << (*str)[i] << endl; // why? error: subscripts requires array or pointer type
cout << str[1] << endl;
cout << (*strr)[1] << endl; // why? error: subscripts requires array or pointer type
}
// 1 this is a char pointer to a char;
Right.
// 2 this is a char array initialised to value "world";
Right, "world\0" is created by the compiler and is put in the read-only memory area of the program. Note that this is called a string literal. Then the string is copied over to the char array d.
// 3 this is char pointer to char array (or array of char pointers)?
That's a char pointer yes, a pointer to a single char.
// are we assigning the memory address (not value) of respective
elements here?
No, you're assigning the values of the elements. This is allowed because str[i] is the same as *(str + i) so you can use the same "array style" access with the pointer str. You're looping over the individual chars you have allocated with new and are assigning them the value of the chars in the char array d.
// why? error: subscripts requires array or pointer type
Because you already dereference str (which is pointing at the start of the 6 element char array) with * which gives you a char, then you try to use that char like an array with [1] which makes no sense. *str would give you 'w' (the first element). And str[1] would give you *(str + 1) which is 'o' (the second element), don't double up.
A small-big side note, string literals are of type const char[], not char[], they're placed in read only memory and thus they can not be altered by the program (don't write to them).
char * strr = "morning";
This is very very bad, it treats a const char[] as a char[], this has been deprecated in the standard for a while now and according to the current standard this is even illegal, yet compilers still allow it for some reason.
Because compilers allow this you could get some nasty situations like trying to modify the string literal:
char * strr = "morning";
strr[0] = 'w'; // change to "worning"
This will attempt to write to read-only memory, which is undefined behaviour and will probably/hopefully get you a segmentation fault. Long story short, use the appropriate type to have the compiler stop you before the code reaches runtime:
const char * strr = "morning";
side side note : don't forget to delete anything you allocated with new.
This question already has answers here:
What is array to pointer decay?
(11 answers)
Closed 7 years ago.
I saw this code in this link-http://www.tutorialspoint.com/cplusplus/cpp_pointers_vs_arrays.htm. Look at the first piece of code.
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have array address in pointer.
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the next location
ptr++;
}
return 0;
}
Shouldn't it be ptr = &var instead of ptr = var? It is below the comment. Why is it declared simply asvar instead of &var?
var will decay into a pointer to its first element.
ptr = var;
is equivalent to
ptr = &var[0];
&var is a pointer to an array, not to an int.
int (*aptr)[MAX] = &var;
would be valid, but it doesn't mean the same - *aptr is an array with MAX elements, not an int.
The tutorial's claim that "pointers and arrays are interchangeable in many cases" is completely wrong.
The only time you can "interchange" anything is this case; when something expects a pointer, an array decays into a pointer to its first element.
There is not a single case where you can use a pointer in place of an array.
Confusingly, ptr is often called "a pointer to an array" or even "an array" in informal conversation, even though this is formally incorrect.
This is because "a pointer to the first element of an array" is quite a mouthful, and to a non-beginner it's usually clear from context what is actually meant.
An array "decays" to a pointer to its first element in assignments, parameter passing etc. That would be a pointer to int, which is what p is declared as.
You actually can take the address of the array, although it is much less common. The address then is the address of the whole array, like this:
int (*parr)[3] = &var;
Now cou can say, for example, int i = (*parr)[1]; to initialize i with the second element of var, 100.
The address of the whole array is numerically identical with the address of its first element because the first element is where the array starts, after all. That may seem funny: What's the point then?
The difference is in type, which (apart from mere grammar questions about type compatibility -- but you can always cast those away in C!) determines what happens when you do pointer arithmetics. Consider
int *ptr = var;
int (*parr)[3] = &var;
printf("ptr: %p, parr: %p\n", ptr, parr);
printf("Increment ptr: %p, incremented parr: %p\n", ptr+1, parr+1);
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
int *ab;
*ab = 5656;
cout << *ab; //These block crashes the app too.
But i can get the hex value of content of pointer if i write this:
int *ab = (int *)5656;
cout << ab; //Output is hex value of 5656.
So i want to ask: * is a operator that brings the contents of pointer(?) but why in this(these) example(s) app crashes?
And i can use that operator if i change code into this:
int a = 5656;
int *aptr = &a;
cout << *aptr; //No crash.
And why dereference operator(*) brings the only first character of a char:
char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr; // Here output = 'this is a test'
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
In this case, you are setting the pointer ab to point at the address 5656. Do you know what's at this address? No you don't. You are telling the compiler to trust you that there is an int there. Then, when you dereference the pointer with *ab, you obviously find that there isn't an int there and you get undefined behaviour. In this case, your program crashes.
int *ab;
*ab = 5656;
cout << *ab;
In this case, you have an uninitialised pointer ab which you then dereference to assign 5656 to the int it points at. Since it's uninitialised, dereferencing it gives you undefined behaviour. Think of it this way. You haven't put an addres in ab so you don't know where it points. You can't just dereference it and hope it points at an int.
int a = 5656;
int *aptr = &a;
cout << *aptr;
This is fine because you know you have an int object with value 5656 and you know that aptr contains the address of that int object. It's perfectly fine to dereference aptr.
const char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr;
(Your code was using a deprecated conversion to char*, so I changed it to a const char*.)
The string literal "this is a test" gives you an array containing const chars. However, it then undergoes array-to-pointer conversion giving you a pointer to its first element. Since each element is a const char, the pointer you get is a const char*. You then store this pointer in cptr.
So cptr points at the first element of the string. Dereferencing that pointer gives you that first element, which is just the first character of the string. So you output t.
The I/O library has special overloads that take const char*s and treat it as pointing to a string of characters. If it didn't, cout << cptr would just print out the address in cptr. Instead, these special overloads will print out the null-terminated array of characters that cptr is assumed to point to.
I think it's worth noting that the application crashes you are observing are due to the fact that it is very unlikely that your process (i.e. program) owns the memory at the location you specify: 5656.
Modern operating systems disallow access to memory allocated by other processes.
Imagine what a headache it would be if that we're not the case: one program could modify the data associated with another one!
The "access violation" message is a helpful hint that you're accessing memory that your process does not own.
is a operator that brings the contents of pointer(?)
No. * is a operator that brings the contents of memory which pointer point to.
Here:
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
Pointer ab contains 5656. *ab tries to access memory which pointer ab point to => *ab tries to access memory at address 5656. Your program is not allowed to access memory at address 5656 because it is not allocated or read-only => app crashes.
And i can use that operator if i change code into this:
int a = 5656; int *aptr = &a; cout << *aptr; //No crash.
Here you allocate and initialize memory: int a = 5656;
Here you write address of previously allocated memory to pointer: int *aptr = &a;
Here you access memory which was previously allocated: *aptr (memory contains 5656).
You have right to access it => app doesn't crash.
And why dereference operator(*) brings the only first character of a char
Because char is not string, char is character. When you dereference pointer to char, you get char.
C has no built-in type for string. That's why it's common to use pointer to memory containing string. This pointer usually points to a first character of string: char * - pointer to character