Practical Programming in C - Lec01

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-087-practical-programming-in-c-january-iap-2010/index.htm をやってみることにした。学んだことをメモしていく。

gccオプション

-I

includeヘッダのpathを指定。

-g

gdbコマンドでデバッグするための情報を追記。

Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2).  GDB can work with this debugging information.

-O

コンパイラの最適化レベルを決める。-O0は最適化をしない。

-Wall

warningsをすべてonにする。

gdbとvalgrind

gdbGNU Debuggerで、gccの-gオプションと組み合わせることでdebugができる。 valgrindはメモリ関連の問題を解析するためのツール。

/proc/[pid]/maps

メモリがどのように確保されているか、知ることができる。 http://www.atmarkit.co.jp/flinux/special/proctune/proctune01b.html http://linuxjm.sourceforge.jp/html/LDP_man-pages/man5/proc.5.html

配列のメモリ確保

テキストには書いてないが、どうなるか調べてみた。

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    int i;
    int x[] = { 1, 2, 3 };

    for (i = 0; i < 10; i++) {
        printf("%p\n", &x[i]);
        printf("%d\n", x[i]);
    }
}
0x7ffff4e79a40
1
0x7ffff4e79a44
2
0x7ffff4e79a48
3
0x7ffff4e79a4c
3
0x7ffff4e79a50
0
0x7ffff4e79a54
0
0x7ffff4e79a58
830598365
0x7ffff4e79a5c
59
0x7ffff4e79a60
0
0x7ffff4e79a64
0

危険。

static宣言

関数にstatic宣言をするとどうなるか?プログラミング言語Cには「外部変数あるいは関数に適用されるstatic宣言は、そのオブジェクトの通用範囲をコンパイルされつつあるソース・ファイルの残りの部分に限定される役割を持つ。」とある。日本語訳が変だが脳内変換すると、コンパイルしているソースからしか見えないということ。

static.h
static int static_function(void);
static.c
#include "static.h"

static int static_function(void)
{
    return 1;
}
hello.c
#include <stdlib.h>
#include <stdio.h>
#include "static.h"

int main(void)
{
    printf("Hello Static Function%d\n", static_function());
    exit(0);
}

とすると

$ gcc static.c hello.c -o hello.o && ./hello.o 
static.h:19: warning: ‘static_function’ used but never defined
Undefined symbols for architecture x86_64:
  "_static_function", referenced from:
      _main in cc96NBns.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

となる。

次に関数内部の変数にstatic宣言をしてみる。プログラミング言語Cには「内部的なstatic変数は特定の関数に局所的である。(中略)内部的なstatic変数には、単一の関数において内輪で永久的なメモリが与えられることを意味する。」とある。

static.c
int function(void)
{
    static int i = 0;
    i++;
    return i;
}
hello.c
int main(void)
{
    int i;
    for ( i = 0; i < 3; i++ ) {
        printf("Hello Static Variable%d\n", function());
    }
    exit(0);
}
$ gcc static.c hello.c -o hello.o && ./hello.o
Hello Static Variable1
Hello Static Variable2
Hello Static Variable3

static宣言のまとめ

  • 関数・外部変数: 外部から参照できなくなる。Javaのprivate宣言に近い。
  • 内部変数: メモリスタックに積まれず、静的に確保される。