Recently, I begin to learn C++ language for Pointer series, I knew the pointer is the specific var what is used to hold the address of another variable. And when we change the value at the memory area which the pointer is hold, it also change the value of that var. So then i just wrote the code to do it.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main(int argc, char const *argv[])
{
int n=5;
int *p=&n; //pointer p hold the address of n
std::cout<<"value of n = "<<n<<endl;
std::cout<<"value of n = "<<*p<<endl;
std::cout<<"value of n= "<<*(&n)<<endl;
std::cout<<"the address of n = "<<&n<<endl;
std::cout<<"the address of n = "<<p<<endl;
*p=19; //change the value at the address of n -> mean n definitely change
std::cout<<"value of n once *p changed = "<<n<<endl;
p++; //p address increase 4 bytes
std::cout<<"address of p changed = "<<p<<endl;
(*p)++;
std::cout<<"address of p = "<<p<<endl;
return 0;
}
then i got the resul below :
As I mark red in my picture, when I do (*p)++ - I understood that the value at the address p hold will increase 1, but once I check the result, it didn't show the value of p after (*p)++ line , just the address of p has increased 1 byte.
What is the reason for this?
If we break down your code into the important parts, we see:
int n=5; // 1.
int *p = &n; // 2.
p++; // 3.
(*p)++; // 4. Dereference and increment.
You clearly have a good grip on what 1-3 do in this code. But, 4 is a big problem. In 3, you changed the pointer. The pointer previously pointed to n, after incrementing, what does it point to now?Wherever it is, it is not necessarily memory that we own and can actively change.
In line 4, you change it. This is undefined behaviour which, from the linked page you can see:
undefined behavior - there are no restrictions on the behavior of the program.
So the program can do pretty much anything.
Your program has undefined behavior.
Let's look at this sequence picked from your program:
int n=5;
int *p=&n;
p++; // p now points to some unknown memory area
(*p)++; // here you dereference `p` - undefined behavior.
You are never allowed to dereference a pointer that is not pointing to an object that is "alive".
Related
I am trying to debug the following code:
Status ListInsert_Sq(SqLIst *L, int i, LElemType_Sq e)
{
LElemType_Sq *newbase;
LElemType_Sq *p, *q;
if(i<1 || i>(*L).length+1)
return ERROR;
if((*L).length >= (*L).listsize)
{
newbase = (LElemType_Sq*)realloc(LElemType_Sq *)realloc((*L).elem, ((*L).listsiz+LISTINCREMENT)*sizeof(LElemType_Sq));
if(!newbase)
exit(OVERFLOW);
(*L).elem = newbase;
(*L).listsize += LISTINCREMENT;
}
q = &(*L).elem[i-1];
for(p=&(*L).elem[(*L).length-1];p>=q;--p)
*(p+1) = *p;
*q = e;
(*L).length++;
return OK;
}
Is using --p correct here?
Specifically I wonder if the last element of the list is going to be moved or overwritten by the previous element?
Thank you!
After rewriting,the guessed intention of the code looks like:
#include <stdlib.h>
#include <string.h>
#include "listmeuk.h"
Status ListInsert_Sq(SqLIst *lp, int index, LElemType_Sq elem)
{
if(index<1 || index>lp->length+1) return ERROR; // this assumes 1-based indexing
index--; // transform to zero-based indexing
if(lp->length >= lp->listsize)
{
LElemType_Sq *newbase;
newbase = realloc(lp->elem, (lp->listsiz+LISTINCREMENT) *sizeof *newbase);
if(!newbase) exit(OVERFLOW);
lp->elem = newbase;
lp->listsize += LISTINCREMENT;
}
if(index < lp->length) memmove(&(lp->elem[index+1]), &(lp->elem[index]), (lp->length-index) * sizeof lp->elem[0] );
lp->elem[index] = elem;
lp->length++;
return OK;
}
This code (in which I have added the missing semicolon):
for(p=&(*L).elem[(*L).length-1];p>=q;--p)
*(p+1) = *p;
sets p to point to the last assigned element in the array elem. Then *(p+1) = *p; copies this last set element to the newly allocated space (allocated with realloc) above. (By “assigned element”, I mean one for which a value had been assigned.)
Then --p decrements the pointer to point to the previous element. (Using arithmetic on pointers works in units of array elements.) Then *(p+1) = *p; copies the second-to-last assigned element to the previous space of the last assigned element. Then the loop continues on this way, effectively moving each element one further space up the array.
Ultimately, the loop appears to be intended to stop when the element with index i-1 has been moved, as q is set to the address of that element with q = &(*L).elem[i-1];.
However, it is defective. If i is one, then q points to the first element of the array, and p will eventually reach that element, and --p will attempt to decrement p to point before the start of the array. The behavior of this attempt is not defined by the C standard. (This presumes L points to the start of the array. It is possible L points into an array beyond its start, in which case this problem does not occur.)
I'm newer in C/C++, I really confuse about a function that executes complex operation. I just want to know how it works ? What does function mean ?
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data){
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
Any idea ??
Update my understanding:
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data) {
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
int main() {
int a[10] = { 0 };
int *p = a;
printf("Before !!\n");
for(int i=0;i<10;i++)
printf("%d ", a[i]);
writetoXX(&p, 20, 30);
printf("After !!! \n");
for (int i = 0; i<10; i++)
printf("%d ", a[i]);
getchar();
return 0;
}
After run this program, I see that the function writetoXX change value arr[0][0] and arr[0][1] to 20 and 30. It means that the function is used for write data to 2 consecutive blocks.
And output is below:
Before !!
0 0 0 0 0 0 0 0 0 0
After !!
20 30 0 0 0 0 0 0 0 0
src is a pointer to a pointer to an unsigned int, for example this is used for bidimensional arrays. Because of the operator precedence, the routine does:
take *src, it is a pointer to an unsigned int
(*src)++ increments the pointer, such that it points to the next unsigned int. It is a post increment, so it returns the value before the increment.
*(*src)++ is the unsigned int pointed by *src before the increment ++
So in summary, you take * src which is a pointer to unsigned int, you assign the first pointed data to reg_offset, then you increment such pointer, then you assign the next element to reg_data, and finally you increment again the pointer *src.
Double pointer is a variable which stores address of another pointer variable.
Consider this *(*src)++ = reg_offset;
In one line: The value of reg_offset is stored at current address stored in src and the address in src is incremented.
You can consider this happening in the following order.
1) As you know src is a variable which is storing address of another pointer or memory space.
2) So (*src) whill give address of the pointed variable or memory space.
3) Due to operator precedence, (*src)++ takes place. Which you can read like, after executing the current line, increment the address value stored in src.
4) Now *(*src) Which is the memory space with address stored in (*src). So *(*src) = reg_offset; will copy the value of reg_offset to that address. I have removed ++ in this line just for clarity.
5) When the second line *(*src)++ = reg_data; is about to be executed, the (*src) will be pointing to next address. So reg_data is written to next address.
Please note, next address does not mean current_address+1. It actually means current_address+sizeof(data type). Ifunsigned int is 4 byte in your compiler, then next_address = current_address+4
You can print content of (*src) in between the lines and verify.
I'm just playing around pre/post increment/decrement in C language. In the program below, everything works fine with variable var. But increments to the pointer variable *varAddress++ return garbage value.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int var = 1;
int *varAddress = &var;
printf("Value befor pre increment %d\n",*varAddress);
++*varAddress;
printf("Value after pre increment %d\n",*varAddress);
printf("Value befor post increment %d\n",*varAddress);
*varAddress++;
printf("Value after post increment %d\n",*varAddress);
return 0;
}
Output
Value befor pre increment 1
Value after pre increment 2
Value befor post increment 2
Value after post increment 1606416400
Program ended with exit code: 0
According to the Operator Precedence, suffix increment has higher precedence than indirection operator, so *varAddress++ is equivalent as:
*(varAddress++);
which will increase the pointer itself, then point to memory unallocated somewhere else, that's why *varAddress will return garbage value (this is UB).
You might want:
(*varAddress)++;
++ has higher precedence than * so by doing *varAddress++ you are moving a pointer to some un-owned location and trying to dereference it, which will lead to undefined behavior.
#include<stdio.h>
void main(){
char arr[] ="abcd";
char *p=arr,*q=arr;
char k,temp;
temp = *p++; /* here first it assigns value present in address which
is hold by p and then p points to next address.*/
k = ++*q;/*here increments the value present in address which is
hold by q and assigns to k and also stores the incremented value in the same
address location. that why *q will get 'h'.*/
printf("k is %c\n",k); //output: k is h
printf("temp is %c\n",temp);//output: temp is g
printf("*p is %c\n",*p);//output: *p is e
printf("*q is %c",*q);//output: *q is h
}
I was curious to know why the addresses of the same array i.e array b in my case is changing before and after it has been passed to the function manipulation(), as shown in the output picture.
Please share your thoughts and help me figure this out. Thank you!
#include <stdio.h>
void manipulation(int *pa,int *pb){
int i;
for(i=0;i<10;i++){
*(pb+i)=*(pa+i);
printf("%d\t %04x\n",*pb+i,&pb+i);
}
}
int main(){
int a[10],b[10];
int i;
int *point;
point = &b[0];
printf("Enter the array elements\n");
for(i=0;i<10;i++){
scanf("%d\n",&a[i]);
}
for(i=0;i<10;i++){
printf("%04x\n",&point+i);
}
manipulation(&a[0],&b[0]);
return 0;
}
because you print (address of your pointer) + i:
printf("%04x\n",&point+i);
printf("%d\t %04x\n",*pb+i,&pb+i);
you want to print the pointer + i:
printf("%04x\n",point+i);
printf("%d\t %04x\n",*pb+i,pb+i);
Also you have a bug in there:
printf("%d\t %04x\n",*pb+i,pb+i);
*pb+i is interpreted as (*pb) + i that is the first value of the array plus i, or simply pb[0]+i.
you seem to get the right answer because your array is 1 2 3 ...
you probably want this:
printf("%d\t %04x\n",*(pb+i),pb+i);
or simply:
printf("%d\t %04x\n",pb[i],pb+i);
Yeah, the real problems is comparing the address of point to the address of pb.
Try using point + i (or &point[i]) and pb + i (or &pb[i]). I'm sure you will get the expected answer.
In case you are curious, &point + i is the location in memory of the local variable point plus the value of i. &pb + i is the location in memory of the parameter pb plus the value of i. They are different variables, so they have different locations in memory.
point stores the address of array a. &point prints the address of point and adding 4 through out the loop. same is the case with &pb. 28fee8 is the place where point is stored and 28fed4 is the place where pb is stored.
I was messing around trying to understand pointers and the operator "new"
and I ended up getting even more confused on what these 2 codes should result to, which is other but its not, so I wanted to understand what happened here.
thanks in advance.
#include <iostream>
using namespace std;
int main()
{
int * p = new int(50);
p[1] = 33;
cout << *p << endl;
}
Output: 50
and when I tried this
#include <iostream>
using namespace std;
int main()
{
int * p = new int[50];
p[1] = 33;
cout << *p << endl;
}
Output: -842150451
I was wondering about the meaning of each result.
In the first case
int * p = new int(50); // allocates 1 int on heap, initialized to value of 50
p[ 1] = 33; // p gives you the address of integer,
// p[1] moves the p pointer forward and accessing
// the pointed object results in undefined behavior,
// this means that at this moment anything can happen
// exception, crash, home war, nothing, everything,
// printing garbage value as well
In the second case:
int* p = new int[50]; // allocates 50 ints on heap, uninitialized
p[ 1] = 17; // initializes element with index 1 to value of 17
std::cout << *p; // p gives you the address of first element, with index 0
// which is still uninitialized, thus prints garbages
You should use
int* p = new int[50]();
to value-initialize ints to 0.
In the first one, you created dynamically a single int with a value of 50. When you try to assign the value 33, you actually assign it in memory that is not yours. It is undefined behaviour. But when you print it, you print the original value you made, which was 50.
In the second one, you created dynamically an array of 50 int. You've then specified the second value of in the array should be 33.* So when you print the value with cout << *p << endl;, you end up printing only the first value, which is undefined. Try it again, you'll probably get another value.
*Edit: as pointed in the comments, I should have been more explicit about this. An array starts at 0. So if you want to access the first value p[0] would do it.
In the first case you're creating an array of 50 ints, assigning a value to the SECOND int in the array, and then printing the first element in the array. Array indices start at 0, so when you dereference the pointer in your cout statement, it's printing whatever happened to be in memory at index 0.
In the second case you're creating a single integer, and initializing it with the value 50. When you dereference the pointer in the print statement, you're getting the integer you just created. The p[1] = 33 may or may not cause an error as your accessing unassigned memory.
int* p = new int[50];
allocates an array of int on the heap with 50 uninitialized elements, ranging from index 0 to 49.
Setting p[1] to 33 doesn't change p[0] which is what you're printing with "cout << *p".
The value -842150451 (0xCDCDCDCD in hex) is a magic number "Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory", see this question on SO.
int* p = new int(50);
allocates exactly one int on the heap and initializes it with the value 50, so setting p[1] afterwards should result in undefined behavior since you didn't allocate that memory where p[1] is referring to.
I'd recommend to use the Visual Studio Memory Windows to see what happens to the memory you're allocating while stepping through your code.