などの文字列リテラル"hello"
は、プログラムの存続期間にわたって保持されるような方法で格納されます。多くの場合、それらは読み取り専用の別のデータ セグメント (スタックまたはヒープとは異なる) に格納されます。
あなたが書くとき
char stack[] = "hello";
タイプ「6要素配列」の新しいauto
(「スタック」)変数を作成しchar
(サイズは文字列リテラルの長さから取得されます)、文字列リテラルの内容がそれ"hello"
にコピーされます。
あなたが書くとき
char *heap = "hello";
タイプ「ポインター」の新しいauto
(「スタック」)変数を作成しており、文字列リテラル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...
この変数には、文字列「hello」を含む さらに別のheap
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;
}