诸如此类的字符串文字"hello"
以这样一种方式存储,即它们在程序的整个生命周期内都被保存。它们通常存储在一个单独的数据段(不同于堆栈或堆)中,该数据段可能是只读的。
当你写
char stack[] = "hello";
您正在创建一个auto
类型为“6 元素数组”的新(“堆栈”)变量char
(大小取自字符串文字的长度),并将字符串文字的内容复制"hello"
到其中。
当你写
char *heap = "hello";
您正在创建一个类型为“pointer to ”的新auto
(“stack”)变量,并将字符串文字的地址复制到其中。 char
"hello"
这是它在我的系统上的外观:
Item Address 00 01 02 03
---- ------- -- -- -- --
"hello" 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
stack 0x7fffb00c7620 68 65 6c 6c hell
0x7fffb00c7624 6f 00 00 00 o...
heap 0x7fffb00c7618 70 0b 40 00 p.@.
0x7fffb00c761c 00 00 00 00 ....
*heap 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
如您所见,字符串文字"hello"
有自己的存储空间,从地址 0x400b70 开始。两个stack
ahdheap
变量都被创建为auto
(“堆栈”)变量。 stack
包含字符串文字内容的副本,而heap
包含字符串文字的地址。
现在,假设我用来malloc
为字符串分配内存并将结果分配给heap
:
heap = malloc( sizeof *heap * strlen( "hello" + 1 ));
strcpy( heap, "hello" );
现在我的内存映射如下所示:
Item Address 00 01 02 03
---- ------- -- -- -- --
"hello" 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
stack 0x7fffb00c7620 68 65 6c 6c hell
0x7fffb00c7624 6f 00 00 00 o...
heap 0x7fffb00c7618 10 10 50 00 ..P.
0x7fffb00c761c 00 00 00 00 ....
*heap 0x501010 68 65 6c 6c hell
0x501014 6f 00 00 00 o...
该heap
变量现在包含一个不同的地址,它指向另一个包含字符串“hello”的 6 字节内存块。
编辑
对于 byteofthat,这是我用来生成上述地图的代码:
垃圾车.h:
#ifndef DUMPER_H
#define DUMPER_H
/**
* Dumps a memory map to the specified output stream
*
* Inputs:
*
* names - list of item names
* addrs - list of addresses to different items
* lengths - length of each item
* count - number of items being dumped
* stream - output destination
*
* Outputs: none
* Returns: none
*/
void dumper(char **names, void **addrs, size_t *lengths, size_t count, FILE *stream);
#endif
自卸车.c:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "dumper.h"
/**
* Dumps a memory map to the specified output stream
*
* Inputs:
*
* names - list of item names
* addrs - list of addresses to different items
* lengths - length of each item
* count - number of items being dumped
* stream - output destination
*
* Outputs: none
* Returns: none
*/
void dumper(char **names, void **addrs, size_t *lengths, size_t count, FILE *stream)
{
size_t i;
int maxlen = 15;
for ( size_t j = 0; j < count; j++ )
{
if (strlen(names[j]) > maxlen && strlen(names[j]) < 50)
maxlen = strlen(names[j]);
}
fprintf(stream,"%*s%15s%5s%5s%5s%5s\n", maxlen, "Item", "Address", "00", "01",
"02", "03");
fprintf(stream,"%*s%15s%5s%5s%5s%5s\n", maxlen, "----", "-------", "--", "--",
"--", "--");
for (i = 0; i < count; i++)
{
size_t j;
char *namefield = names[i];
unsigned char *p = (unsigned char *) addrs[i];
for (j = 0; j < lengths[i]; j+=4)
{
size_t k;
fprintf(stream,"%*.*s", maxlen, maxlen, namefield);
fprintf(stream,"%15p", (void *) p);
for (k = 0; k < 4; k++)
{
fprintf(stream,"%3s%02x", " ", p[k]);
}
fprintf(stream, " ");
for ( k = 0; k < 4; k++)
{
if (isgraph(p[k]))
fprintf(stream,"%c", p[k]);
else
fprintf(stream, ".");
}
fputc('\n', stream);
namefield = " ";
p += 4;
}
fputc('\n', stream);
}
}
以及如何使用它的示例:
#include <stdio.h>
#include "dumper.h"
int main(void)
{
int x = 0;
double y = 3.14159;
char foo[] = "This is a test";
void *addrs[] = {&x, &y, foo, "This is a test"};
char *names[] = {"x", "y", "foo", "\"This is a test\""};
size_t lengths[] = {sizeof x, sizeof y, sizeof foo, sizeof "This is a test"};
dumper(names, addrs, lengths, 4, stdout);
return 0;
}