-4

look at the two line c code and output: code:

char * str = "hello world!";
printf("h at heap memory address: %p\n",str);
printf("str pointer stack memory address: %p\n",&str);

and output:

h at heap memory address: 0x4008a8
str pointer stack memory address: 0x7ffc9e7ceb90

the memory address length for heap and stack is 0x4008a8, 0x7ffc9e7ceb90 respectively. Why memory address for heap is 3 bytes whereas memory address for stack is 6 bytes? Something related to virtual memory and paging ?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • `0x4008a8` can have as as many leading 0's in front as is necessary to fill out the address the width of a pointer – Michael Petch Dec 13 '15 at 23:18
  • @MichaelPetch don't think so, every try will get the same 3 bytes length in heap. – Jizhou Zhang Dec 13 '15 at 23:22
  • The question is vague. I read it that there are 2 questions. He seems uncertain why `0x4008a8` is 3 bytes. Internally both pointers will be the same width. The other question appears to be about the layout of user space as it relates to the stack/heap/code. Both are pointers nonetheless. – Michael Petch Dec 13 '15 at 23:25
  • 5
    'Heap' is usually reserved for referencing the data allocated by `malloc()` and friends. The string literal is probably stored in the code segment, where it will be non-writable. Ultimately, there's no 'reason' for the addresses other than 'that is where the implementation stored the items whose addresses you are printing'. What did you expect? Why do you think there's a problem? – Jonathan Leffler Dec 13 '15 at 23:27
  • Possible duplicate of [What and where are the stack and heap?](https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap) – Schwern Dec 13 '15 at 23:32
  • For 64-bit Windows, this MSDN documentation might be of interest: https://msdn.microsoft.com/en-us/library/windows/hardware/hh439648(v=vs.85).aspx – Michael Petch Dec 13 '15 at 23:40
  • 1
    Did you expect the *real meaning of it all* to print as `42` ? – chqrlie Dec 13 '15 at 23:40
  • Presumably addresses on your system are 64 bits. `printf` formats address without leading zeros. Think of them as `0x00000000004008a8` and `0x00007ffc9e7ceb90`. They're both 8 bytes; they just happen to have different values, indicating that they're in different regions of the virtual memory space. – Keith Thompson Dec 14 '15 at 00:09
  • 1
    @chqrlie I need some Babel Fish to translate. – Michael Petch Dec 14 '15 at 00:12

3 Answers3

4

Try this instead:

char * str = "hello world!";
printf("h at heap memory address: %p (%zu bytes)\n", str, sizeof(str));
printf("str pointer stack memory address: %p (%zu bytes)\n", &str, sizeof(&str));

Using the sizeof operator, we can print the actual size of the two pointers. (%zu is a format specifier for an unsigned result from sizeof—it is probably equivalent to %lu on your system.)

You'll see that in both cases, the pointer actually takes up 8 bytes (64 bits).

The reason that the hexidecimal representations displayed by printf only show 3 or 6 bytes is because printf drops any leading zeros. Consider this similar example:

int i = 10;
printf("%x\n", i);

The result will just be "a", but that doesn't mean that i only takes up one byte.

DaoWen
  • 32,589
  • 6
  • 74
  • 101
0

@JohnathanLeffler nailed it. "The string literal is probably stored in the code [data] segment, where it will be non-writable." You can see this with a little more probing.

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

/* Do this in a function so I can verify what is stack and what is heap.
 * Try to return a variable and see if the compiler warns that it's
 * stack memory!
 */
static char *test_mem() {
    char *stack = "whom";
    char *heap = malloc(sizeof(char) * 5);

    printf("char *stack = \"%s\" at %p (size %zu) inner %p (size %zu)\n",
           stack, stack, sizeof(stack), &stack, sizeof(&stack));
    printf("char *heap = malloc at %p (size %zu) inner %p (size %zu)\n",
           heap, sizeof(heap), &heap, sizeof(&heap));

    return heap;
}

int main(void)
{
    char *ret = test_mem();
    printf("%s\n", ret);
    return 0;
}

char *stack = "whom" at 0x102fc0f28 (size 8) inner 0x7fff5cc3f4d8 (size 8)
char *heap = malloc at 0x7f9362404c80 (size 8) inner 0x7fff5cc3f4d0 (size 8)

Note that only the string literal is in the lower memory address. All the rest are in basically the same location. When I open up the executable in a hex editor I can find a block of strings.

00000f20: dcff ffff 2573 0a00 7768 6f6d 0063 6861  ....%s..whom.cha
00000f30: 7220 2a73 7461 636b 203d 2022 2573 2220  r *stack = "%s" 
00000f40: 6174 2025 7020 2873 697a 6520 257a 7529  at %p (size %zu)
00000f50: 2069 6e6e 6572 2025 7020 2873 697a 6520   inner %p (size 
00000f60: 257a 7529 0a00 6368 6172 202a 6865 6170  %zu)..char *heap
00000f70: 203d 206d 616c 6c6f 6320 6174 2025 7020   = malloc at %p 
00000f80: 2873 697a 6520 257a 7529 2069 6e6e 6572  (size %zu) inner
00000f90: 2025 7020 2873 697a 6520 257a 7529 0a00   %p (size %zu)..

The string foo is not stored in the heap, it is in the data segment of the executable which, as you guessed, is accessed as virtual memory which is allocated a special range.

Finally, the output shows those pointers are all of the same size. They're all (in my case) 64 bit (8 byte) pointers.

Schwern
  • 153,029
  • 25
  • 195
  • 336
0

Explanation

Note that pointers are still variables in C and the only thing that makes them special is that they have the special * notation beside them. The value of a pointer is the address it refers to, just like the value of an int is the value it is assigned to

char * str = "hello world!";
printf("h at heap memory address: %p\n",str);
printf("str pointer stack memory address: %p\n",&str);

They both use the pointer specifier (%p) which is used to print memory address of a value. Note this is implementation defined.

  • The first one prints the memory address of the string literal "hello world!", i.e. the value of the pointer str
  • The second prints the memory address of the pointer i.e. the memory address of str

As for why these values are so far apart, @DaoWen already answered this and it has nothing to do with virtual pages or whatnot.

Community
  • 1
  • 1
smac89
  • 39,374
  • 15
  • 132
  • 179
  • Clean and simple. Expand just a little bit to explain how these 2 addresses can appear so far apart. – chqrlie Dec 14 '15 at 00:17
  • "*As for why these values are so far apart... it has nothing to do with virtual pages or whatnot.*" This is incorrect. The constant string `"hello world!"` is in the data segment of the executable. `str`'s address is so different because it points to that section of virtual memory – Schwern Dec 14 '15 at 02:20
  • @Schwern What I meant is that the answer I referred to did not mention virtual pages as the reason why they are so far apart – smac89 Dec 14 '15 at 02:23
  • @Smac89 Yes, that answer doesn't address why they're far apart at all. Only that they're all the same size pointer. [I cover why they're so far apart](http://stackoverflow.com/a/34257756/14660). – Schwern Dec 14 '15 at 03:11