6

I'm just starting C. I have read about pointers in various books/tutorials and I understand the basics. But one thing I haven't seen explained is what are the numbers.

For example:

int main(){
   int anumber = 10;
   int *apointer;

   apointer = &anumber;

   printf("%i", &apointer);
   }

may return a number like 4231168. What does this number represent? Is it some storage designation in the RAM?

Searock
  • 6,278
  • 11
  • 62
  • 98
  • 1
    Related: http://stackoverflow.com/questions/4819876/c-pointers-what-values-are-held-here/4819926#4819926 – James Feb 17 '11 at 17:22
  • printing pointers with `%i` is [undefined behavior](https://stackoverflow.com/q/16864552/995714). You must use [`%p`](https://stackoverflow.com/q/9053658/995714) – phuclv May 30 '21 at 01:30

11 Answers11

10

Lots of PC programmer replies as always. Here is a reply from a generic programming point-of-view.

You will be quite interested in the actual numerical value of the address when doing any form of hardware-related programming. For example, you can access hardware registers in a computer in the following way:

#define MY_REGISTER (*(volatile unsigned char*)0x1234)

This code assumes you know that there is a specific hardware register located at address 0x1234. All addresses in a computer are by tradition/for convenience expressed in hexadecimal format.

In this example, the address is 16 bits long, meaning that the address bus on the computer used is 16-bits wide. Every memory cell in your computer has an address. So on a 16-bit address bus you could have a maximum of 2^16 = 65536 addressable memory cells. On a PC for example, the address would typically be 32 bits long, giving you 4.29 billion addressable memory cells, ie 4.29 Gigabyte.

To explain that macro in detail:

  • 0x1234 is the address of the register / memory location.
  • We need to access this memory location through a pointer, so therefore we typecast the integer constant 0x1234 into an unsigned char pointer = a pointer to a byte.
  • This assumes that the register we are interested in is 1 byte large. Had it been two bytes large, we would perhaps have used unsigned short instead.
  • Hardware registers may update themselves at any time (their contents are "volatile"), so the program can't be allowed to make any assumptions/optimizations of what's stored inside them. The program has to read the value from the register at every single time the register is used in the code. To enforce this behavior, we use the volatile keyword.
  • Finally, we want to access the register just as if it was a plain variable. Therefore the * is added, to take the contents of the pointer.

Now the specific memory location can be accessed by the program:

MY_REGISTER = 1;
unsigned char var = MY_REGISTER;

For example, code like this is used everywhere in embedded applications.

(But as already mentioned in other replies, you can't do things like this in modern PCs, since they are using something called virtual addressing, giving you a slap on the fingers should you attempt it.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • BTW, in many embedded systems, the register is just defined a `const` pointer (the value in the pointer is constant), the dereferencing occurs in the code and not the macro. – Thomas Matthews Feb 17 '11 at 19:08
  • 1
    @Thomas That is a dangerous style, as you may suddenly do accidental pointer arithmetic, for example: int x = MY_REGISTER + 0x01; If MY_REGISTER is a pointer, the compiler is free to implicitly cast the address to an int. Also, making pointer constant inside a macro like this fills no purpose beyond visual appeal, it will not prevent any bugs. – Lundin Feb 18 '11 at 08:44
7

It's the address or location of the memory to which the pointer refers. However, it's best if you regard this as an opaque quantity - you are never interested in the actual value of the pointer, only that to which it refers.

How the address then relates to physical memory is a service that the system provides and actually varies across systems.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Unless you're doing pointer math to find another piece of data in an array. – BMitch Feb 17 '11 at 14:12
  • 3
    @B Mitch In that case you don't care about the absolute address, only offset or relative address – David Heffernan Feb 17 '11 at 14:12
  • 1
    A minor quibble--never is too strong a word. It really depends upon the environment and application. There are many cases (certainly not all) in both embedded systems and drivers where we are interested in the actual value of the pointer (or at the very least its approximate value). – Sparky Feb 17 '11 at 14:40
  • 1
    @Sparky I know, never say never and all that. I was just trying to get across the sentiment concisely to someone who is clearly just starting out as a programmer. Nuances like virtual addressing, paging, file backed memory, kernel/user don't need to be tackled to get a good grounding in how pointers work. And if you try to say everything then the main message is lost. But you are right of course. – David Heffernan Feb 17 '11 at 14:42
3

That's a virtual address of anumber variable. Every program has its own memory space and that memory space is mapped to the physical memory. The mapping id done by the processor and the service data used for that is maintained by the operating system. So your program never knows where it is in the physical memory.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • Whether it is a virtual address or a physical address is an implementation detail. Kernel mode programs would refer to physical addresses. – David Heffernan Feb 17 '11 at 14:10
2

It's the address of the memory1 location where your variable is stored. You shouldn't care about the exact value, you should just know that different variables have different addresses, that "contiguous memory" (e.g. arrays) has contiguous addresses, ...

By the way, to print the address stored in a pointer you should use the %p specifier in printf.


  1. Notice that I did not say "RAM", because in most modern OSes the "memory" your process sees is virtual memory, i.e. an abstraction of the actual RAM managed by the OS.
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
1

A lot of people told you, that the numeric value of a pointer will designate its address. This is one way how implementations can do it, but it is very important, what the C standard has to say about pointers:

  • The nil pointer has always numeric value 0 when operated on in the C programming language. However the actual memory containing the pointer may have any value, as long as this special, architecture dependent value is consistently treated nil, and the implementation takes care that this value is seen as 0 by C source code. This is important to know, since 0 pointers may appear as a different value on certain architectures when inspected with a low level memory debugger.
  • There's no requirement whatsoever that the values of the pointer are in any way related to actual addresses. They may be as well abstract identifiers, resolved by a LUT or similar.
  • If a pointer addresses an array, the rules of pointer arithmetic must hold, i.e. int array[128]; int a, b; a = (int)&array[120]; b = (int)&array[100]; a - b == 20 ; array + (a-b) == &array[20]; &array[120] == (int*)a
  • Pointer arithmetic between pointers to different objects is undefined and causes undefined behaviour.
  • The mapping pointer to integer must be reversible, i.e. if a number corresponds to a valid pointer, the conversion to this pointer must be valid. However (pointer) arithmetic on the numerical representation of pointers to different objects is undefined.
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Eh? Your array example is wrong. a - b will be 120-100 = 20 int elements. Or 20*sizeof(int) = 80 bytes, on a 32-bit machine. – Lundin Feb 18 '11 at 08:54
  • Eh, you're right of course, in some way. The thing is, one must be able to do proper pointer arithmetic with the integer representation as well. – datenwolf Feb 18 '11 at 09:56
0

it is not the address of the variable anumber that is printed but it is the address of the pointer which gets printed.look carefully.had it been just "apointer",then we would have seen the address of the anumber variable.

0

Yes, exactly that - it's the address of the apointer data in memory. Local variable such as anumber and apointer will be allocated in your program's stack, so it will refer to an address in the main() function's frame in the stack.

If you had allocated the memory with malloc() instead it would refer to a position in your program's heap space. If it was a fixed string it may refer to a location in your program's data or rodata (read-only data) segments instead.

Rup
  • 33,765
  • 9
  • 83
  • 112
0

in this case &apointer represent the address in RAM memory of the pointer variable apointer

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
0

apointer is the "address" of the variable anumber. In theory, it could be the actual physical place in RAM where the value of anumber is stored, but in reality (on most OS'es) it's likely to be a place in virtual memory. The result is the same though.

Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
0

It's a memory address, most likely to the current location in your program's stack. Contrary to David's comment, there are times when you'll calculate pointer offsets, but this is only if you have some kind of array that you are processing.

BMitch
  • 231,797
  • 42
  • 475
  • 450
0

It's the address of the pointer.

"anumber" takes up some space in RAM, the data at this spot contains the number 10.

"apointer" also takes up some space in RAM, the data at this spot contains the location of "anumber" in RAM.

So, say you have 32 bytes of ram, addresses 0..31

At e.g. position 16 you have 4 bytes, the "anumber" value 10

At e.g. position 20 you have 4 bytes, the "apointer" value 16, "anumber"'s position in RAM.

What you print is 20, apointer's position in RAM.

Note that this isn't really directly in RAM, it's in virtual address space which is mapped to RAM. For the purpose of understanding pointers you can completely ignore virtual address space.

Erik
  • 88,732
  • 13
  • 198
  • 189