21819


# やりたいこと

read()等で読み込んだ入力バッファに対し、ポインタキャストを駆使してメモリ効率の良いコーディングを行いたい。

# 知りたいこと

下記のコードをgcc 5.3/clang
3.7にてコンパイルするとwarningが出力されますが、言語仕様として「正しい」記述を行い、warningを消したく思っております。  
表現として合っているかも自信がないのですが、表題の通り異なる要素数のポインタ配列キャストがそもそも推薦されていない、ポインタ配列キャストは問題ないがC99等規格から見ると記述が間違っている等々、ツッコミビリティが高い/低いに関わらず、気になった所をご指摘いただきたく思います。  
また、C言語の勉強中の身でもありますので、ISO/IEC 9899:1999やJIS X
3010:2003等の公式規格のどの部分を参照すれば良いのか(該当箇所なのか)教えていただけると非常に嬉しく思います。

よろしくお願いいたします。

## サンプルコード

[code]

    #include <stdio.h>
    
    int main(int argc, char const* argv[]) {
      unsigned char ary1[64] = {"Hello World!"};
      unsigned char(*ary2)[16] = {0};
    
      // warning: incompatible pointer types assigning...
      ary2 = &ary1;
    
      printf("%s\n", *ary2);
    
      return 0;
    }
    
[/code]

# 2016/02/07 23:23編集

実行環境等の記載を忘れていました。申し訳ありません。

[code]

     % lsb_release -a
    LSB Version:    1.4
    Distributor ID: Arch
    Description:    Arch Linux
    Release:        rolling
    Codename:       n/a
    
     % clang -v
    clang version 3.7.1 (tags/RELEASE_371/final)
    Target: x86_64-unknown-linux-gnu
    Thread model: posix
    Found candidate GCC installation: /usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0
    Found candidate GCC installation: /usr/lib64/gcc/x86_64-unknown-linux-gnu/5.3.0
    Found candidate GCC installation: /usr/sbin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0
    Found candidate GCC installation: /usr/sbin/../lib64/gcc/x86_64-unknown-linux-gnu/5.3.0
    Selected GCC installation: /usr/sbin/../lib64/gcc/x86_64-unknown-linux-gnu/5.3.0
    Candidate multilib: .;@m64
    Selected multilib: .;@m64
    
     % clang -std=c11 -Wall -Wextra test.c
    test.c:7:8: warning: incompatible pointer types assigning to 'unsigned char (*)[16]' from 'unsigned char (*)[64]' [-Wincompatible-pointer-types]
      ary2 = &ary1;
           ^ ~~~~~
    test.c:3:14: warning: unused parameter 'argc' [-Wunused-parameter]
    int main(int argc, char const* argv[]) {
                 ^
    test.c:3:32: warning: unused parameter 'argv' [-Wunused-parameter]
    int main(int argc, char const* argv[]) {
                                   ^
    3 warnings generated.
    
[/code]


CC BY-SA 3.0
2016-02-07T14:02:46.553
21816
2016-02-07T15:38:48.367
2016-02-07T14:27:46.173
14314
14314
question
c
異なる要素数のポインタ配列キャストのWarningを消したい

[code]

    unsigned char ary1[64] = {"Hello World!"};
    unsigned char(*pary1)[64] = &ay1;
    unsigned char(*pary2)[16] = pary1;
    
[/code]

とすればわかるでしょうか？
ここで`pary1[1]`は64バイト先を指すのに対し`pary2[1]`は16バイト先を指す。このように異なる型での代入だから危険であり、警告されています。


CC BY-SA 3.0
2016-02-07T14:46:04.593
21818
2016-02-07T14:46:04.593
4236
21816
answer


そもそものタイトルにある「ポインタ配列」と言う表現ですが、「ポインタの配列」(ポインタを複数個持ちたいので配列にしている)なのか「配列へのポインタ」を持ちたいのかどちらなのでしょうか。

ちなみにあなたのコード:

[code]

    unsigned char(*ary2)[16] = {0};
    
[/code]

は、「配列`unsigned char[16]`へのポインタ」を表しています。ary1の方は、`unsigned
char[64]`型ですから、&ary1は「配列`unsigned char[64]`へのポインタ」になります。警告が出て当然だと思うんですが。

C言語では、式中の配列は(通常の文脈では)配列の先頭要素へのポインタに変換されますから、「配列へのポインタ」はかなりややこしい存在で、結構ベテランのCプログラマーでも取り扱いを間違えることがあります。ポインタについて理解が不十分なまま使わない方が良いでしょう。  
キャストという言葉も通常C言語では`(型)式`の形のキャスト構文の使用を表しますが、あなたの元のコードにはキャスト構文は出てきていないですね。

あなたが提示されたコードを普通に書くとこうなります。(何をしたいのか具体的に示されていないので、余分なところはそぎ落としました。)

[code]

    unsigned char ary1[64] = {"Hello World!"};
    unsigned char *ary2 = NULL;
    
    ary2 = ary1;
    
    printf("%s\n", ary2);
    
    return 0;
    
[/code]

C言語流に慣れていないと`ary2 =
ary1;`のところが、配列全体を代入していて効率が悪く見えるのかもしれませんが、先に書いたように先頭要素へのポインタを代入しているだけです。

ちなみにコメント中で「値渡し」と言う言葉を連発しておられますが、通常「値渡し」と言うのは関数呼び出しのパラメータに使われる言葉で、代入文で配列の中身全部が渡されるのか先頭のアドレスだけが渡されるのか、を表す場合に使う言葉ではありません。

とりあえず、ISOだのJISだの気張らずに、自分の理解が不十分なところを洗い出して、少しずつ解決していくことをお勧めします。


CC BY-SA 3.0
2016-02-07T15:38:48.367
21819
2016-02-07T15:38:48.367
13972
21816
answer