12764


①int型の宣言について

[code]

    int count[1 << CHAR_BIT] = { 0 };
    
[/code]

というものがあったのですが、よく分かりません。  
調べてみるとCHAR_BITは8以上と書かれていましたが、このint型の宣言の意味は分かりませんでした。

②for文について

[code]

    char *p = "ABCDEFG";
    for ( ; *p ; p++) { ～｝
    
[/code]

普通のfor文ではfor(int i = 0; i < 10;
i++)となりますが、この場合はどういうことなのでしょうか。*pの長さの分（7文字あるので7回。そのため初期値が必要ない）ということでいいのでしょうか。

よろしくお願いします。


CC BY-SA 3.0
2015-07-28T06:55:33.067
12763
2015-07-28T08:51:36.583
9850
question
c
C言語のint型の宣言とfor文について


# ① int型の宣言について

`<<` はビットシフト演算子といいます。int は32bit整数(処理系によります)ですので2進数で表すと `0000 0000 0000 0000`
となります。数値の1であれば `0000 0000 0000 0001` となります。  
ここで `1 << 8` とするとビットが左に8個動きます。つまり `0000 0001 0000 0000`
となります。これを10進数に戻すと256になります。つまり

[code]

    int count[1 << CHAR_BIT] = {0};
    
[/code]

は

[code]

    int count[256] = {0};
    
[/code]

と同じになり、intが256個格納出来る配列 count をゼロクリアで宣言する、という意味になります。

# ② for 文について

for 文は、`初期化式; 継続条件式; 再初期化式` という書式を取ります。p
は既に1行上で初期化されているので初期化式としては必要がありません。また継続条件式 `*p` は評価すると文字列の NUL ターミネータで false
になり、かつ最初期化式が `p++` であることから、文字列の中の文字全てを処理する、という意味になります。  
for 文の中で `printf("%c\n", *p);` すると全ての文字でループしている事が分かると思います。


CC BY-SA 3.0
2015-07-28T07:16:33.737
12764
2015-07-28T07:16:33.737
2020-06-17T08:14:45.997
-1
440
12763
answer


①をフォローしておこう。  
`CHAR_BIT` とは `char` に格納できるビット数  
`CHAR_BIT` が 8 だったら `char` には 256 種類の文字が格納できることになる。  
`CHAR_BIT` が 16 だったら `char` には 65536 種類の文字が格納できることになる。  
`1 << CHAR_BIT` はこの文字種類数を算出しているわけだ。  
ということで提示コードは `char` に格納できる文字種類のカウンタを用意している。  
たぶん、後から [同じ文字が何個現れたか] を数えようとしているんだろう。


CC BY-SA 3.0
2015-07-28T07:47:31.407
12766
2015-07-28T07:47:31.407
8589
12763
answer


以下は回答ではないのですが、デバッガを利用して処理の過程をある程度視覚化してみると分かりやすくなるかもしれません。  
実行環境としては Linux、C コンパイラは gcc、デバッガには gdb を使用します。

[code]

    #include <stdio.h>
    #include <limits.h>
    
    int main() {
      int count[1 << CHAR_BIT] = { 0 };
    
      printf("%d\n", count[0]);
    }
    
[/code]

上記のソースコードを `main.c` として保存して、デバッグ情報付きでコンパイル・リンクします。

[code]

    $ gcc -g -o main main.c
    
[/code]

gdb を起動します。

[code]

    $ gdb main
         :
    (gdb) 
    
[/code]

main 関数にブレークポイント(breakpoint)を設定して実行します。

[code]

    (gdb) break main
    Breakpoint 1 at 0x400511: file main.c, line 5.
    (gdb) run
    Starting program: /home/nemo/main
    Breakpoint 1, main () at main.c:5
    5         int count[1 << CHAR_BIT] = { 0 };
    
[/code]

count 変数の初期化の直前で実行が停止します。この時点での count 変数(配列)の中身を表示してみましょう。

[code]

    (gdb) p count
    $1 = {2090266759, 0, 32660418, 0, 7, 0, -7648, 32767, -140378680, ...
    
[/code]

C では変数宣言と同時に初期化はしてくれないので(だから初期化が必要なのですが)、配列にランダムな値が入っています。  
次に、count 変数のサイズ(配列の要素数)を表示してみましょう。

[code]

    (gdb) p sizeof(count)/sizeof(int)
    $2 = 256
    
[/code]

`sizeof` は C に用意されている `sizeof` 演算子と同じです。count 変数は int 型の配列なので `/sizeof(int)`
とすることで要素数を計算しています。

ところで、`CHAR_BIT` の具体的な値ですが、デバッガからでは直接には分かりません。

[code]

    (gdb) p CHAR_BIT
    No symbol "CHAR_BIT" in current context.
    
[/code]

コンパイルの段階(正確にはプリプロセッサによる処理(プリプロセス)の段階)で置き換えられてしまい、実行ファイルにもデバッグ情報にも記録されていません。一例として、以下を実行することで知ることができます。

[code]

    $ printf "#include <limits.h>\n_CHAR_BIT = CHAR_BIT\n" | gcc -E - | tail -1
    _CHAR_BIT = 8
    
[/code]

話を戻して、gdb での処理を進めてみましょう。

[code]

    (gdb) step
    7         printf("%d\n", count[0]);
    
[/code]

step 命令でブレークポイントの次の 1 statement が実行されます(count 変数の初期化)。

[code]

    (gdb) p count
    $3 = {0 <repeats 256 times>}
    
[/code]

配列の全ての要素が 0 になりました。

なお、gdb では変数の値を変更することも可能です。例えば、count 変数(配列)の先頭要素に 1 をセットしてみます。

[code]

    (gdb) set count[0] = 1
    (gdb) p count
    $4 = {1, 0 <repeats 255 times>}
    
[/code]

まぁ、モダンな IDE(Visual Studio や Eclipse など)では以上の様な事を GUI
で実行できるのではないかと思います。使ったことがないので分かりませんが…。

以上、ご参考までにどうぞ。


CC BY-SA 3.0
2015-07-28T08:38:55.203
12768
2015-07-28T08:51:36.583
2015-07-28T08:51:36.583
12763
answer