C言語のメモリ管理

変数と関数がメモリ上でどのように割り当てられているか実験
#include <stdio.h>
#include <stdlib.h>

int global;
static int stglobal;

void func (int p) {
    static int s;
    int local;

    printf("parameter addr : %p\n", &p);
    printf("function static addr : %p\n", &s);
    printf("func local addr : %p\n", &local);
}

int main(void) {
    char *alloc = malloc(1000);

    func(100);

    printf("allocated addr : %p\n", alloc);
    printf("global var addr : %p\n", &global);
    printf("static var addr : %p\n", &stglobal);
    printf("func () addr : %p\n", func);
    printf("main() addr : %p\n", main);
    printf("addr of printf : %p\n", printf);

    return 0;
}

出力結果
parameter addr : 0x7fff68308afc
function static addr : 0x10870a078
func local addr : 0x7fff68308af8
allocated addr : 0x1088008f0
global var addr : 0x10870a080
static var addr : 0x10870a07c
func () addr : 0x108709ce0
main() addr : 0x108709d50
addr of printf : 0x7fff8b7f9222

このように配置されているはず

プログラム領域
func() addr : 0x108709ce0
main() addr : 0x108709d50

静的記憶領域
function static addr : 0x10870a078
static var addr : 0x10870a07c
global var addr : 0x10870a080

動的記憶領域(ヒープ)
allocated addr : 0x1088008f0

スタック
func local addr : 0x7fff68308af8
parameter addr : 0x7fff68308afc

printfのアドレスはプログラム領域になるはずだが、スタックのアドレスに近い場所になっている。
原因は不明。

バイトオーダー。基本データ型がメモリのどこに配置されているか調べる

prmem関数は指定アドレスから指定バイト数だけのメモリの内容を16進数で表示する

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

void prmem (const void *_p, int n) {
    /* signed char(-128-127)ではなくunsigned char(0-255)と解釈させる */
    const unsigned char *p = _p;
    char i, j;

    for (i=0; i<n; ++i, ++p) {
        printf("%02x", *p);
    }
}


int main(void) {
    char c = 0x12;
    short h = 0x1234;
    long l = 0x12345678;
    int i = 0x12345678;

    float f = 2.3;
    double g = 2.3;
    double fg;

    printf("char %p : %02x :", &c, c);
    prmem(&c, sizeof(c));
    printf("\n");
    
    printf("short %p : %02x :", &h, h);
    prmem(&h, sizeof(h));
    printf("\n");

    printf("long %p : %04x :", &l, l);
    prmem(&l, sizeof(l));
    printf("\n");
    
    printf("int %p : %04x :", &i, i);
    prmem(&i, sizeof(i));
    printf("\n");
    
    printf("float %p : %20.16f :", &f, f);
    prmem(&f, sizeof(f));
    printf("\n");

    printf("float %p : %20.16f :", &g, g);
    prmem(&g, sizeof(g));
    printf("\n");

    fg = f;
    printf("float %p : %20.16f :", &fg, fg);
    prmem(&fg, sizeof(fg));
    printf("\n");

    printf("double - float : %g\n", g - fg);

    return 0;
}

出力結果
char 0x7fff6aa44b17 : 12 :12
short 0x7fff6aa44b14 : 1234 :3412
long 0x7fff6aa44b08 : 12345678 :78563412
int 0x7fff6aa44b04 : 12345678 :78563412
float 0x7fff6aa44b00 : 2.2999999523162842 :33331340
float 0x7fff6aa44af8 : 2.2999999999999998 :6666666666660240
float 0x7fff6aa44af0 : 2.2999999523162842 :0000006066660240
double - float : 4.76837e-08

使用したPCはx86系の為最下位バイトが最初のアドレスに、最上位バイトが最後のアドレスに記憶される
⇒1234だと34 12の順にメモリに配置される