51章 記憶クラス指定子と型修飾子

http://www.geocities.jp/ky_webid/c/051.html

なにやらまたもや色々複雑そうな予感がしますよ。

まずは記憶クラス指定子

  • extern指定子
  • static指定子
  • auto指定子
  • register指定子
  • typedef指定子


externとstaticは以前習いました。

autoとregisterは覚えなくても良いようです。一応概念だけは抑えておきましょう。

ということでこの章でのメインの話はtypedefになります。

typedefとは自作の型を定義できる指定子です。

これ、物凄く便利ですね。今後いっぱい使うと思います。

そして型修飾子

  • const修飾子
  • volatile修飾子


constは初期化以外で変数の上書きを禁止する修飾子です。

ポインタにconstを使う場合は書き方が二種類あってそれぞれで意味が異なるので注意が必要です。

// pが指す先の変数を変更できない
const int *p; 

// pが保持しているアドレスを変更できない
int *const p;  

// pが保持しているアドレスも、pが指す先の変数も変更できない
const int *const p;

volatile修飾子はいまいちどういったものか良く分からないですね。

具体例が無いのでどういう場合に最適化が間違ってしまうのかが知りたいところです。

問題1

次の記号定数を、const修飾子を使った変数に書き換えて下さい。

#define NUMBER (500)
#define PAI (3.141592)
#define NAME ("TANAKA")

簡単です。

const int NUMBER = 500;
const float PAI = 3.141592;
const char NAME[] = "TANAKA";
答え合わせ

解答例では

const char *str = "TANAKA";

となっていました。配列じゃなくポインタで定義する場合はこれで変更不可にできるのでOKですね。

問題2

次のようなメンバを持つ構造体を使い、各メンバに適当な初期値を与え、それを画面に表示するプログラムを作って下さい。ただし、typedef指定子を使って下さい。

構造体のメンバ
 int型のnum
 char型のc
 float型のf

typedefの問題です。

int main (int argc,char *argv[]) {
    typedef struct {
        int num;
        char c;
        float f;
    } DATA;
    DATA data = {10,'A',3.14};
    
    printf("num = %d\n",data.num);
    printf("c = %c\n",data.c);
    printf("f = %f\n",data.f);
    return 0;
}

できました。迷う部分はないですね。

問題3

typedef指定子を使って、ポインタ変数や、配列に別名を付けて、実際にその別名を使用するプログラムを作って下さい。

ん?変数名に別名をつける?別名の型を使った変数を宣言して使用するっていう問題でいいんだよね?

int main () {
    typedef int int2;
    typedef char* cp;
    
    int2 num[] = {1,2,3};
    cp str = "FOO";
    
    printf("num[0] = %d\n",num[0]);
    printf("num[1] = %d\n",num[1]);
    printf("num[2] = %d\n",num[2]);
    printf("str = %s\n",str);
    return 0;
}

できました。ポインタもtypedefで定義できてしまうんですね。

いつも僕がポインタ定義する際に変数側に*を付けてるので一瞬どうかけばいいかわからなかったんですが、もしかしてと思って試してみたらいけました。凄いですねtypedef。

答え合わせ
typedef int* pint;     /* int型のポインタの別名pint */
typedef int aint[10];  /* int[10]の別名aint */

あ、凄い。配列の要素まで指定して型を作れるんだ。なんかこれ何でもできそうですよねtypedefって。