看两行c代码并输出: 代码:
char * str = "hello world!";
printf("h at heap memory address: %p\n",str);
printf("str pointer stack memory address: %p\n",&str);
并输出:
h at heap memory address: 0x4008a8
str pointer stack memory address: 0x7ffc9e7ceb90
堆和堆栈的内存地址长度分别为0x4008a8,0x7ffc9e7ceb90。为什么堆的内存地址是3个字节而堆栈的内存地址是6个字节?与虚拟内存和分页有关的东西?
答案 0 :(得分:4)
请改为尝试:
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));
使用sizeof
运算符,我们可以打印两个指针的实际大小。 (%zu
是来自sizeof
的无符号结果的格式说明符 - 它可能等同于您系统上的%lu
。)
你会发现,在这两种情况下,指针实际占用8个字节(64位)。
由printf
显示的十六进制表示仅显示3或6个字节的原因是因为printf
丢弃任何前导零。考虑这个类似的例子:
int i = 10;
printf("%x\n", i);
结果只是“a”,但这并不意味着i
只占用一个字节。
答案 1 :(得分:0)
@JohnathanLeffler钉了它。 "字符串文字可能存储在代码 [data]段中,在那里它是不可写的。" 你可以看到这个更多的探索。
#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)
请注意,只有字符串文字位于较低的内存地址。所有其余的基本上都在同一个位置。当我在十六进制编辑器中打开可执行文件时,我可以找到一个字符串块。
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)..
字符串foo
未存储在堆中,它位于可执行文件的data segment中,正如您所猜测的那样,它被作为virtual memory访问,并被分配了一个特殊范围。
最后,输出显示那些指针的大小都相同。它们都是(在我的情况下)64位(8字节)指针。
答案 2 :(得分:0)
请注意,指针仍然是C中的变量,唯一使它们变得特殊的是它们旁边有特殊的*
符号。指针的值是它引用的地址,就像int的值是它赋给的值
char * str = "hello world!";
printf("h at heap memory address: %p\n",str);
printf("str pointer stack memory address: %p\n",&str);
它们都使用指针说明符(%p
),用于打印值的内存地址。 请注意,这是实施定义。
str
str
至于为什么这些值相距甚远,@DaoWen已经回答了这个问题,它与虚拟页面或其他什么无关。