1

I have the following question. Why is there a difference in the addresses of the two pointers in following example? This is the full code:

#include <stdio.h>
#include <stdlib.h>

void *mymalloc(size_t bytes){
void * ptr = malloc(bytes);
printf("Address1 = %zx\n",(size_t)&ptr);
return ptr;
}

void main (void)
{
unsigned char *bitv =  mymalloc(5);
printf("Address2 = %zx\n",(size_t)&bitv);
}

Result:

Address1 = 7ffe150307f0
Address2 = 7ffe15030810
Antonis V
  • 27
  • 6

4 Answers4

2

It's because you are printing the address of the pointer variable, not the pointer. Remove the ampersand (&) from bitv and ptr in your printfs.

printf("Address1 = %zx\n",(size_t)ptr);

and

printf("Address2 = %zx\n",(size_t)bitv);

Also, use %p for pointers (and then don't cast to size_t)

WHY?

In this line of code:

 unsigned char *bitv =  mymalloc(5);

bitv is a pointer and its value is the address of the newly allocated block of memory. But that address also needs to be stored, and &bitv is the address of the where that value is stored. If you have two variables storing the same pointer, they will still each have their own address, which is why &ptr and &bitv have different values.

But, as you expected, ptr and bitv will have the same value when you change your code.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
1

Why is there a difference in the addresses of the two pointers

Because the two pointers are two different pointer(-variable)s, each having it's own address.

The value those two pointer(-variable)s carry in fact are the same.

To prove this print their value (and not their address) by changing:

  printf("Address1 = %zx\n",(size_t)&ptr);

to be

  printf("Address1 = %p\n", (void*) ptr);

and

  printf("Address2 = %zx\n",(size_t)&bitv);

to be

  printf("Address2 = %p\n", (void*) bitv);
alk
  • 69,737
  • 10
  • 105
  • 255
0

In your code you used to print pointer's address following code:

printf("%zx", (size_t)&p);

It doesn't print address of variabele it's pointing to, it prints address of pointer.

You could print address using '%p' format:

printf("%p", &n); // PRINTS ADDRESS OF 'n'

There's an example which explains printing addresses

int n;
int *v;

n = 54;
v = &n;

printf("%p", v); // PRINTS ADDRESS OF 'n' 
printf("%p", &v); // PRINTS ADDRESS OF pointer 'v'
printf("%p", &n); // PRINTS ADDRESS OF 'n'
printf("%d", *v); // PRINTS VALUE OF 'n'
printf("%d", n); // PRINTS VALUE OF 'n'

So your code should be written like this:

void * get_mem(int size)
{
     void * buff = malloc(size); // allocation of memory
     // buff is pointing to result of malloc(size)
     if (!buff) return NULL; //when malloc returns NULL end function
     //else print address of pointer
     printf("ADDRESS->%p\n", buff);
     return buff;
}

int main(void)
{
    void * buff = get_mem(54);
    printf("ADDRESS->%p\n", buff);
    free(buff);
    return 0;
}
Adam
  • 33
  • 4
  • "*to print pointer's address use '%p' `printf("%p", v);`*" This does not print the address of `v`, but its value. – alk Nov 05 '17 at 14:59
  • `&(size_t)p` would be an error. And does not occur in the question. I think you meant to say `(size_t)&ptr`. – M.M Nov 05 '17 at 21:31
-2

(In addition to other answers, which you would read first and probably should help you more ...)

Read a good C programming book. Pointers and addresses are very difficult to explain, and I'm not even trying to. So the address of a pointer &ptr is generally not the same as the value of a pointer (however, you could code ptr= &ptr; but you often don't want to do that)... Look also at the picture explaining virtual address space.

Then read more documentation about malloc: malloc(3) Linux man page, this reference documentation, etc... Here is fast, standard conforming, but disappointing implementation of malloc.

read also documentation about printf: printf(3) man page, printf reference, etc... It should mention %p for printing pointers...

Notice that you don't print a pointer (see Alk's answer), you don't even print its address (of an automatic variable on the call stack), you print some cast to size_t (which might not have the same bit width as a pointer, even if on my Linux/x86-64 it does).

Read also more about C dynamic memory allocation and about pointer aliasing.

At last, read the C11 standard specification n1570.

(I can't believe why you would expect the two outputs to be the same; actually it could happen if a compiler is optimizing the call to mymalloc by inlining a tail call)

So I did not expect the output to be the same in general. However, with gcc -O2 antonis.c -o antonis I've got (with a tiny modification of your code)....

a surprise

However, if you declare the first void *mymalloc(size_t bytes) as a static void*mymalloc(size_t bytes) and compile with GCC 7 on Linux/Debian/x86-64 with optimizations enabled, you do get the same output; because the compiler inlined the call and used the same location for bitv and ptr; here is the generated assembler code with gcc -S -O2 -fverbose-asm antonis.c:

    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Address1 = %zx\n"
.LC1:
    .string "Address2 = %zx\n"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB22:
    .cfi_startproc
    pushq   %rbx    #
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
# antonis.c:5: void * ptr = malloc(bytes);
    movl    $5, %edi    #,
# antonis.c:11: {
    subq    $16, %rsp   #,
    .cfi_def_cfa_offset 32
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    leaq    8(%rsp), %rbx   #, tmp92
# antonis.c:5: void * ptr = malloc(bytes);
    call    malloc@PLT  #
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    leaq    .LC0(%rip), %rdi    #,
# antonis.c:5: void * ptr = malloc(bytes);
    movq    %rax, 8(%rsp)   # tmp91, ptr
# antonis.c:6: printf("Address1 = %zx\n",(size_t)&ptr);
    movq    %rbx, %rsi  # tmp92,
    xorl    %eax, %eax  #
    call    printf@PLT  #
# antonis.c:13: printf("Address2 = %zx\n",(size_t)&bitv);
    leaq    .LC1(%rip), %rdi    #,
    movq    %rbx, %rsi  # tmp92,
    xorl    %eax, %eax  #
    call    printf@PLT  #
# antonis.c:14: }
    addq    $16, %rsp   #,
    .cfi_def_cfa_offset 16
    popq    %rbx    #
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE22:
    .size   main, .-main

BTW, if I compile your unmodified source (without static) with gcc -fwhole-program -O2 -S -fverbose-asm I'm getting the same assembler as above. If you don't add static and don't compile with -fwhole-program the two Adddress1 and Address2 stay different.


two run outputs

I run that antonis executable and got on the first time:

/tmp$ ./antonis
Address1 = 7ffe2b07c148
Address2 = 7ffe2b07c148

and the second time:

/tmp$ ./antonis
Address1 = 7ffc441851a8
Address2 = 7ffc441851a8

If you want to guess why the outputs are different from one run to the next one, think of ASLR.

BTW, a very important notion when coding in C is that of undefined behavior (see also this and that answers and the references I gave there). You don't have any in your question (it is just unspecified behavior), but as my contrived answer shows, you should not expect a particular behavior in that precise case.

PS. I believe (but I am not entirely sure) that a standard conforming C implementation could output Address1= hello world and likewise for Address2. After all, the behavior of printf with %p is implementation defined. And surely you could get 0xdeadbeef for both. More seriously, an address is not always the same (of the same bitwidth) than a size_t or an int, and the standard defines intptr_t in <stdint.h>

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    Basil!! :-) :-) No DV from me, no .. but well ... – alk Nov 05 '17 at 15:02
  • 2
    Should we call you Sheldon, from now on?! ;-) – alk Nov 05 '17 at 15:05
  • Sorry, I am not a native English speaker (I'm French). Who is Sheldon ? – Basile Starynkevitch Nov 05 '17 at 15:06
  • [Sheldon](https://en.wikipedia.org/wiki/Sheldon_Cooper) is a character appearing in the US soap ["The Big Bang Theory"](https://en.wikipedia.org/wiki/The_Big_Bang_Theory#The_Theorists). – alk Nov 05 '17 at 15:11
  • @BasileStarynkevitch: **Every** result on the first page of Google results for “Sheldon” answers that question (and I checked both google.com and google.fr, using private mode to avoid personal context). If you are going to respond to questions rudely with statements like “Read a good C programming book,” don’t you think you should learn to use elementary tools yourself? – Eric Postpischil Nov 05 '17 at 15:12
  • The advice to read a good C programming book is IMHO not rude (no insult was written, no insult was meant). But explaining pointers in an answer of a few dozen lines seems impossible to me. Feel free to add a better answer. However I took care to give several links to related terminology. – Basile Starynkevitch Nov 05 '17 at 15:13
  • @BasileStarynkevitch: Well, then consider that you have learned something: Responding to a genuine question with a statement to read a book is rude. (Sheldon is known for failing to understand etiquette.) That is particularly so since your response does not answer the question, and hence was voted down. Additionally, it is not difficult to explain the OP’s key mistake: They printed the addresses of pointer rather than the values of pointers. See, that was not impossible at all, was it? – Eric Postpischil Nov 05 '17 at 15:15
  • But I mentioned that in my answer. First sentence of third paragraph. And I was suprised (but not that much) to find some way to compile the code to get *identical* output for `Address1` and `Address2`. – Basile Starynkevitch Nov 05 '17 at 15:16
  • 1
    @BasileStarynkevitch: Yes, you do answer the question. But it nearly drowns in the rest of your elaborations, which are not obvious for everybody to be related to the question. – alk Nov 05 '17 at 15:18
  • The rest explains that a good enough compiler is allowed to give the same output – Basile Starynkevitch Nov 05 '17 at 15:20
  • @BasileStarynkevitch: At first, I thought alk was being a bit harsh. But, given the additional information you have provided, I agree, you should study Sheldon. The first sentence of your third paragraph does mention the issue, but it is oblique, not tutorial, does not isolate the key issue, and even that sentence, let alone the entirety of your response, obscures the issue with irrelevancies. It is not helpful. – Eric Postpischil Nov 05 '17 at 15:21
  • I believe that my answer is helpful, even to newbies, because it make people think of optimizations. The other answers explained how to print an address. I don't need to repeat that. – Basile Starynkevitch Nov 05 '17 at 15:22
  • @BasileStarynkevitch: It is generally considered rude to imply, even indirectly, that people are ignorant. I do not entirely agree with that rule, as ignorance is the natural state we are born into, and people ought to be open to learning, but it is nonetheless a feature of the society we find ourselves in. By telling somebody to read a book, and especially opening with it instead of opening with an answer to their question, and bolding it, you imply they are ignorant and have failed in a some duty to immediately comprehend complex things without help. It is rude and not helpful. – Eric Postpischil Nov 05 '17 at 15:48
  • On the other hand, we cannot teach what a pointer is in only a few dozen of sentences. No answer here did try do to that. And I improved my answer that I won't even try to. – Basile Starynkevitch Nov 05 '17 at 15:50
  • @BasileStarynkevitch: There is no reason to believe the OP does not understand what a pointer does. They merely appear to have a little confusion about the value of a pointer object versus its address. – Eric Postpischil Nov 05 '17 at 15:50
  • 1
    Confusing a pointer with its address is not understanding what a pointer does. I made the same mistake 30 years ago (as in the OP's question), but that was because at that time I did not understand what a pointer is. – Basile Starynkevitch Nov 05 '17 at 15:51
  • @BasileStarynkevitch: I doubt the confusion is actually about what a pointer is. It is likely just about the syntax. – Eric Postpischil Nov 05 '17 at 15:51
  • We need to agree to disagree. I believe it is about [semantics](https://en.wikipedia.org/wiki/Semantics_(computer_science)) and you think it is about syntax. I did taught semantics of location at university (denotational semantics of Scheme, which is much simpler than C) and it took several courses of 2 hours each (about 10 hours in total IIRC). I am unable to teach what a pointer is in a few pages. I'm not even trying to. – Basile Starynkevitch Nov 05 '17 at 15:53
  • I guess I would need ten hours of lectures to teach what a pointer is (to absolute beginners). What is your estimate? But indeed, I never taught that. – Basile Starynkevitch Nov 05 '17 at 15:55
  • BTW, [compcert](http://compcert.inria.fr/) try to formalize what a pointer is from the compiler point of view, and it is *very* difficult. – Basile Starynkevitch Nov 05 '17 at 16:01