0

Hey I'm fairly new to programming in C, and I'm trying to understand pointers and addresses and running this code I get the output: v = 3003 'a memory address' *p = 3003

I understand the last two, but could someone help explain why v = 3003? My initial understanding would be that it results in 3002, so i understand the addressing and pointer line 'p = &v' is playing a role in this but i don't understand how. Any explanation would be much appreciated thank you!

#include <stdio.h>
int main() {
    int v = 0x3002;
    int* p = 0x3000;
    p = &v;
    (*p)++;
    printf("v = %x\n", v);
    printf("%x\n", p);
    printf("*p = %x\n", *p);
}
thin580
  • 1
  • 2
  • 2
    p points at v. You increment what p points at, so you increment v. So v is 3003. – Tim Nov 10 '17 at 09:01
  • 2
    What is your expected and your actual output? Please [edit] your question and make that clear there. – Jabberwocky Nov 10 '17 at 09:01
  • 4
    `(*p)++;` is the other way of saying `v++` here. In short you're doing `v=v+1`. Have a bit of research about pointers. – sjsam Nov 10 '17 at 09:04
  • 1
    it says? my actual output is 3003, but expected output is 3002? – thin580 Nov 10 '17 at 09:07
  • 1
    `printf("%x\n", p);` --> `printf("%p\n", (void*)p);` – BLUEPIXY Nov 10 '17 at 09:10
  • regarding: `int* p = 0x3000; p = &v;` the initial value in 'p' is being overlayed/replaced by the address of 'v' so these two lines can be replaced by: `int *p = &v;` – user3629249 Nov 12 '17 at 16:47
  • this line: `(*p)++;` increments the contents of 'v' from `0x3002` to `0x3003` – user3629249 Nov 12 '17 at 16:49
  • this statement: `printf("%x\n", p);` is trying to print the contents of the pointer 'p' However, this statement is using the wrong conversion (address to unsigned int) Suggest: `printf("%p\n", (void*)p);` where the '%p' is the format specifier for printing the contents of a `void*` and the `(void*)p` is casting the `int*`` to type `void*` – user3629249 Nov 12 '17 at 16:54
  • This statement: `printf("*p = %x\n", *p);` uses a inplicit conversion from `int` to `unsigned int` – user3629249 Nov 12 '17 at 16:56

5 Answers5

5

The behaviour of your code is undefined. You cannot assign an address to a pointer which corresponds to memory that you don't own, with the exceptions of NULL, one past the end of an array, or one past the end of a scalar. (For some reason, this is a little known rule.)

So your first job is to remove int* p = 0x3000;. Replace with int* p;. Then the undefined behaviour goes away.

Your code

p = &v;
(*p)++;

is setting the p to the address of v, and incrementing v via the pointer.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • `int* p = 0x3000;` itself may be undefined but is the outcome of the program really undefined as we reassign `p` on the next line? – Jabberwocky Nov 10 '17 at 09:09
  • @MichaelWalz: Yes it is. One bit of UB equals whole program UB. Although I would put a compiler that eats your cat as a result of the arbitrary initialisation into the severely hostile category, and switch vendor. – Bathsheba Nov 10 '17 at 09:10
  • Dereferencing doesn't matter. I'm talking about the assignment. Yes when you discover this rule for the first time, it generates a similar reaction to that when you discover that Father Christmas does not exist. **You cannot assign anything.** – Bathsheba Nov 10 '17 at 09:12
  • 1
    @Bathsheba.: Can you please show the standard excerpt? – user2736738 Nov 10 '17 at 09:13
  • I'm not trying to change the code, I'm actually taking this from a past Exam question where it wants me to identify the output. – thin580 Nov 10 '17 at 09:13
  • I'm not yet convinced on the UB part... as long as the invalid pointer is never read (like in pointer arithmetic), and certainly never dereferenced. – grek40 Nov 10 '17 at 09:17
  • Have a look at the accepted answer to the following: contains a C standard reference https://stackoverflow.com/questions/3838855/is-storing-an-invalid-pointer-automatically-undefined-behavior – Bathsheba Nov 10 '17 at 09:23
  • @Bathsheba your linked example is a completely different beast, since a valid pointer is used to calculate an invalid pointer by subtraction and that value is then used in a comparison. I don't see how the case of constant assignment without any attempted usage would be the same thing. – grek40 Nov 10 '17 at 09:29
  • It's little more than a "way in" to this concept. IIRC this is scattered across the C and C++ standards rather than being constrained to a particular paragraph. But rest assured, I'm right! – Bathsheba Nov 10 '17 at 09:31
1

p = &v;

p now contains address of v.

(*p)++;

Increase the value that is at the address contained in p. That value is 0x3002;

So it becomes 0x3003.

Now v is changed via p.

That's why that output.

You can assign to pointer via casting.

int *p=(int*)0x3000;

The code will be :-

#include <stdio.h>
int main() {
    int v = 0x3002;
    int* p;
    p=&v; 
    (*p)++;
    printf("v = %x\n", v);
    printf("%x\n", p);
    printf("*p = %x\n", *p);
}

Also assigning to a pointer variable is undefined behavior

From standard §6.3.2.3

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.)

user2736738
  • 30,591
  • 5
  • 42
  • 56
  • 2
    `int *p = 0x3000;` is legal in C (no need to cast), you only get a warning. But it is irrellevant here anyway. – Jabberwocky Nov 10 '17 at 09:05
  • @MichaelWalz.: Just mentioned....I first thought it is dererenced..but it is not. Checked the code once. – user2736738 Nov 10 '17 at 09:05
  • That was my understanding for why p = 3003, so if two different variables share the same address, any change to one changes the other as well? – thin580 Nov 10 '17 at 09:06
  • @thin580.: To variables can never have same address....but yes via pointer we can modify another...as shown here. – user2736738 Nov 10 '17 at 09:06
  • 2
    @thin580 the `p = 3003` is irrellevant. The code would be the same if you just wrote `int* p;` because `p` is reassigned on the next line anyway. – Jabberwocky Nov 10 '17 at 09:07
  • @MichaelWalz.: Yes..that's right. That's irrelevant. – user2736738 Nov 10 '17 at 09:07
  • It's only irrelevant insofar that `int x = INT_MAX + 1; x = 0;` is not UB. And it certainly is. Just don't assign integers to pointers (unless your compiler allows it by extension; for embedded stuff &c.). Pretty please, with sugar on top. – Bathsheba Nov 10 '17 at 09:32
  • @Bathsheba.: My reference is relevant to the answer I hope? – user2736738 Nov 10 '17 at 09:32
  • @coderredoc: Sort of. The concept is scattered across the standard IIRC. – Bathsheba Nov 10 '17 at 09:33
1

The p=&v statement assigns the address of the variable v to p. In other words, from then on, p is pointing to the memory address where v stores its value. Then (*p)++ increments it: p is a pointer in memory, *p is dereferencing this address so that the increment operation ++ does not apply to p (in which case p would point to the next memory address) but to the value at the address given by p.

Fabien Bouleau
  • 464
  • 3
  • 11
0

First of all, before going into the details of pointer , the Memory access provided by C language is dangerous to use in this way. usually you don't define the addresses of the locations you want to save variable at or the address of the pointer itself as you mentioned in the code.

#include <stdio.h>
int main() {
    int v = **0x3002**;
    int* p = **0x3000;**
    p = &v;
    (*p)++;
    printf("v = %x\n", v);
    printf("%x\n", p);
    printf("*p = %x\n", *p);
}

However, the value you assign to p is neglected since you are using p = &v , the p has the correct address assigned to v by compiler or OS. when you define int v; at run time a memory location is allocated then p will get the address.

in general you are trying to make an integer variable and a pointer to this variable to have two references to the same variable.

In general you don't need to keep track of the address values for variable or pointers when you are using them , you just need to know how to use them properly and when to use them

General Examlpe for pointer usage

#include <stdio.h>
void changeA( int*);
int main() {
   int a=1;
   printf("%d",a);
   changeA(&a);
   printf("%d",a);
   return 0;
}

void changeA(int* pA){
  *pA=2;
}

Output 1 2

the previous example shows the usage of pointers where you can access variables with a different scope , variable a is defined within the scope of main function , and by using the pointers by providing the address of the variable a for the function changeA the function can access the memory location where the variable a is saved in the memory and change it directly from another function scope.

usually pointers used when you need to have multiple outputs for a function and the return can be used to return only one variable. with pointers you will have unlimited capabilities of each function.

BassamJ
  • 1
  • 2
0

here is a correctly written version of the posted code, with appropriate comments

#include <stdio.h>

int main( void ) 
{
    int v = 0x3002;   // sets an integer value into 'v'
    int* p = &v;      // get address of 'v' and places that address in 'p'
    (*p)++;           // increments the contents of 'v', 
                      // using 'p' 
                      // while paying attention to operator precedence in C

    // displays on terminal, the contents of 'v' I.E.0x3003
    printf("v = %x\n", v);   

    // displays on terminal, the address of 'v' (contents of 'p')
    printf("%p\n", (void*)p);

    // displays on terminal, the contents of 'v', which is pointed to by 'p'
    printf("*p = %x\n", (unsigned int)*p);
}
user3629249
  • 16,402
  • 1
  • 16
  • 17