6

Consider the really simple code below:

#include <stdio.h>
#include <stdlib.h>
int main() {

    int* a = (int*) malloc(10 * sizeof(int));
    printf("a = %p, a+1 = %p", a, a+1);
    return 0;
}

The output is this:

a = 0x127f190, a+1 = 0x127f194

Since the size of an int is 4 bytes, I am assuming from the result above that a pointer value is then the index of a byte on my RAM memory. Hence a+1 increases in fact the value of a by sizeof(int) = 4 (bytes). Is that correct?

If yes, then why do I get 32 bit memory addresses from my program? This machine is 64bit running a 64bit version of Ubuntu. How do I get the program to print a full 64bit address? Do I have to compile it with special flags?

Deanie
  • 2,316
  • 2
  • 19
  • 35
  • There's no reason a pointer value should correspond to an "*index of a __byte__ on [your] RAM memory*". – obataku Aug 26 '12 at 18:28
  • What does it mean then? Also, why does then `a+1` actually increase the pointer value by `sizeof(int) = 4`? –  Aug 26 '12 at 18:29
  • 2
    You need to compile it with 64 bit target gcc. – Daniel Aug 26 '12 at 18:32
  • As Dani pointed out, you may want to verify GCC, and this will give some help: http://stackoverflow.com/questions/682934/is-there-a-gcc-preprocessor-directive-to-check-if-the-code-is-being-compiled-on – James Black Aug 26 '12 at 18:33
  • @curvature because you are alocation an array of consecutive elements so 'a' is the address of the first element a[0], 'a+1' the address of the second a[1] and so on – Thanatos Aug 26 '12 at 18:33
  • The address will a virtual address in your case. And you probably compiled the app in 32bit mode, which can still run on a 64bit system if the OS supports it. – Pete Aug 26 '12 at 18:34
  • @Dani: what is the gcc flag that does 64 bit compilation? –  Aug 26 '12 at 18:45
  • `-m64` should do it. See [here](http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html). – Nathan Andrew Mullenax Aug 26 '12 at 19:00
  • A 32-bit executable would explain why there were 8 digits instead of 16. It does not explain why there are 7 digits, as shown in this question. I submit that printf omitting leading zeroes is a better explanation than the width of the pointer, unless this implementation uses 28-bit addresses. – Eric Postpischil Aug 26 '12 at 23:04
  • 1
    @bitmask A manifestation of the [RAS syndrome](http://en.wikipedia.org/wiki/RAS_syndrome). – Daniel Fischer Aug 27 '12 at 10:53

5 Answers5

7

You are correct about your pointer. Memory is traditionally organized and addressed in bytes, pointers point to the first byte of whatever they are pointing to (EDIT: they don't HAVE to, but on the usual platforms and compilers they do).

You are not seeing a "64 bit" pointer simply because the output strips the leading 0s :-) If you do a sizeof(a), chances are that you'll get "4" on a 32 bit system, and "8" on a 64 bit system.

Christian Stieber
  • 9,954
  • 24
  • 23
  • Or it's a 32-bit executable. As one would hope, 64 bit windows still supports 32-bit exes. There's a rundown of 64-bit compilers on [this question](http://stackoverflow.com/questions/9730012/how-can-i-compile-c-on-64bit-windows-to-make-a-64bit-exe) – Nathan Andrew Mullenax Aug 26 '12 at 18:38
  • 1
    Linux systems tend to be less specific about such "details"; they actually aren't all that good at executing 32 bit code unless you have a whole bunch of libs installed, and their package managers might refuse installation of 32 bit apps because it's the "wrong architecture". Thus, the default when it comes to compiling is based on the system that runs the compiler. – Christian Stieber Aug 26 '12 at 18:42
  • I found the flag I was looking for: `-march=core2`. However, `sizeof(int)` is still `4` and the pointer addresses are printed in the exact same format. –  Aug 26 '12 at 18:51
  • That's not the right option. I think it's `-m64`. Also, on the standard unix LP64 model, `int` is *always* 32 bits. Only `long` and pointer types become 64-bit. – R.. GitHub STOP HELPING ICE Aug 26 '12 at 18:54
  • I found such option at http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html. Anyway, I want the pointer values to represent the 64bit nature of the addresses they point to. –  Aug 26 '12 at 19:00
  • @curvature: in the cases where you've built a 32bit executable, the addresses pointed to don't have 64bit nature. This is all "just" virtual address space anyway -- a 32 bit process has a 32 bit address space as far as the program is concerned, regardless of what OS or hardware is hosting it. – Steve Jessop Aug 26 '12 at 19:03
  • Heck, with the X32 ABI, you can even have 32 bits pointers in a 64 bits process. And DOS managed to even mix 16 and 32 bits pointers in a single process. – MSalters Aug 27 '12 at 08:43
4

the index of a byte on my RAM memory

That's close enough for most purposes, but not entirely accurate. It's the index of a byte in your process's address space. Virtual addresses do not relate directly to physical RAM, there's a thing called a "virtual memory manager" that's responsible for keeping track of what virtual addresses in each process refer to what physical RAM (and things other than RAM).

Normally you can forget about this, and just think of the virtual address space as RAM (or as "memory" to keep it abstract). But the same virtual address in different processes could refer to different physical memory, or the same memory could be referred to in different processes by different virtual addresses. Or the same virtual address in the same process could refer to different physical memory at different times, if the OS has noticed that the page hasn't been used for a while, swapped it to disk and then back to memory when it's used again. So it's not really "the" address of the RAM itself, it's just the address that your process has been given by the OS, to refer to some RAM.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Got it. So how do I print now pointer values representing actual 64 bit addresses? –  Aug 26 '12 at 20:40
  • In a 32 bit process, you can't. At least not without modifying the kernel or a kernel-mode device driver. – Steve Jessop Aug 26 '12 at 21:01
  • But I am already compiling the code with 64bit flags (using `-m64` on gcc). Shouldn't that automatically already make the switch? –  Aug 26 '12 at 21:20
1

The reason you're seeing an increase of four is because you're allocating memory for integers, which are fixed at four bytes long (in Intel Linux gcc) -- whether you've compiled 32bit or 64bit code. As already said, the pointers you get refer to virtual memory addresses, not physical memory.

If you change your int to long, you'll see a 4 byte increase with 32bit code and an 8 byte increase with 64bit code.

Additionally, if you look at sizeof(void *) it will tell you if your pointers are 32bit or 64bit. If your pointers are 64bit, then you'll be getting 64bit pointers printed with %p.

I edited your program to run on my copy of Ubuntu, adding:

printf("Size of pointer = %d\n", (int)sizeof(void *));

Here's the output:

a = 0x2067010, a+1 = 0x2067014
Size of pointer = 8

So the pointer is indeed 64bit.

teppic
  • 8,039
  • 2
  • 24
  • 37
0

When you wrote int* a = (int*) malloc(10 * sizeof(int));, you were allocating memory for an array of ten elements. That is equivalent to int a[10]; and a = 0x127f190 is the address of the first element a[0].

Makoto
  • 104,088
  • 27
  • 192
  • 230
Thanatos
  • 1,176
  • 8
  • 18
0

Sorry, to not point you an exact answer. But here it comes:

Look for Pointer Arithmetic, you will find all you are looking for.

Even if you system runs x64, most of the compilers come default with x86 unless you specifically declare to compile for x64. So search compiler documentation for x64 flag, and for relevant options.

Seçkin Savaşçı
  • 3,446
  • 2
  • 23
  • 39