マホ C

と、勝手に呼んでみた。「魔法の C プログラミング演習書」。C 言語初心者の自分には、すごく面白い。よい意味で、懇切丁寧に説明されていない。なので、イヤでも手を動かさなければならない。

魔法のCプログラミング演習書- 入門から実践まで -

魔法のCプログラミング演習書- 入門から実践まで -

柴田氏の「新・明解 C 言語」シリーズとは、真逆のコンセプトのように思う。柴田氏の著書は、図が多く、解説も丁寧で、非常にわかりやすい(実際、お世話になっている)。まさに、正統派。

ちなみに、MMGames 氏の「苦しんで覚えるC言語(通称、苦 C)」が、とても面白かった。ムダを省いた、凝縮された情報により、短時間で C 言語の基本が身につくようになっている。自分は、この「苦 C」で入門した。「苦しんで覚える」とあるが、むしろ、楽しく読めた。

あ、入社 1 年目のときに「K&R」と「UNIXネットワークプログラミング入門」は読んでた。なので、本当の入門は、このときかもしれない。もっとも、はるか昔なので、ほとんど覚えていないが。


で、「難しい」って言いたくないけど、C 言語って、難しいのね。


環境は、相変わらず、Windows 10 上の、Visual Studio Community 2017。空のプロジェクトを作成して、拡張子が c のファイルを追加すると、それっぽくなる。「C やってるな」って感じに。
で、[Ctrl]+[F5] で実行する。何も設定せずにプログラムを実行すると、コマンドプロンプトが起動するものの、実行完了時に終了してしまい、標準出力などが観られない。そこで、プロジェクトのプロパティから「リンカー > システム」で、サブシステムを「コンソール (/SUBSYSTEM:CONSOLE)」にしてあげるとよい。
リアルタイムにコンパイルエラーを教えてもらえるし、デバッグも簡単に出来るし、統合開発環境バンザイである。

2017/04/30 早速追記「4.3 void ポインタ」

こんなことができるんだ。
自分の環境では、テキストの「char temp[len];」の部分が、コンパイルできなかったので、変更した。

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

void swap(void *a, void *b, size_t len) {
    void *tmp;
    tmp = calloc(1, len);
    if (tmp == NULL) return;

    memcpy(tmp, a, len);
    memcpy(a, b, len);
    memcpy(b, tmp, len);

    free(tmp);
    return;
}

void test_swap_double(void) {
    double x = 123.45, y = 67.89;

    swap(&x, &y, sizeof(x));

    printf("x = %6.2f, y = %6.2f\r\n", x, y);
}
2017/06/10 追記「4.4 関数ポインタ」

関数ポインタは、本当にいけてる。さくっと書いてみる(問題読み間違えてたから修正した)。

#include <stdio.h>

void print(char chrs[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%c ", chrs[i]);
    }
    printf("\r\n");
}

int digit2X(char chr) {
    if ('0' <= chr && chr <= '9') {
        return 'X';
    } else {
        return chr;
    }
}

void apply(char chrs[], int (*func)(int)) {
    for (int i = 0; i < strlen(chrs); i++) {
        chrs[i] = func(chrs[i]);
    }
}

void main(void) {
    char chrs[] = { 'A', '1', 'B', '2', 'C', '3' };
    int size = 6;
    print(chrs, size);

    int (*func)(int) = digit2X;

    apply(chrs, func);

    print(chrs, size);
    return;
}
2017/07/08 追記「5.2 不変性」

まぁこれは、こんなもんだろうね。キャストすると、不変性が「引き剥がされて」しまうあたりが、C っぽい。

#include<stdio.h>

typedef struct {
    int x, y;
} point;

void print_point(point const *p) {
    printf("ADDRESS: %p, ", p);
    printf("VALUE X: %d, ", p->x);
    printf("VALUE Y: %d\n", p->y);
    return;
}

void main() {
    point const P = {13, 17};
    point const *Q = &P;

    print_point(Q);
    /* 
     * Q->x = 12; Q->y = 16; ⇒ コンパイルエラー
     * 「式は変更可能な左辺値である必要があります」
     */
    return;
}