2009-08-27 11 views
4

this質問を参照するとlitbの特に受け入れanswerを渡す、私は疑問に思う:私はconstを排除定数行列

void func(const int (*ip)[3]) { 
    printf("Value: %d\n", ip[1][1]); 
} 

int main() { 
    int i[3][3] = { {0, 1, 2} , {3, 4, 5}, {6, 7, 8} }; 
    func(i); 
    return 0; 
} 

場合、コンパイラは、静止しています。私は何か誤解しましたか? funcが配列を変更しないようにしたいと思っていました。

EDIT:

typedef int Array[3][3]; 

void func(const Array *p) { 
    printf("Value: %d\n", (*p)[1][1]); 
} 

int main() { 
    Array a = { {0, 1, 2}, {3, 4, 5}, {6, 7, 8} }; 
    func(&a); 
    return 0; 
} 

私は受け入れるが、この種のコードは、より多くのCのような、非常にCのスタイルではありません++:私は私の行列のデータ型を定義する場合同じことが起こります。 C++では、Arrayをすべての行列の振る舞いを含むクラスとして定義すると、実際には問題はありません。

class Array {...}; 

私は、Cの配列の配列と配列の概念をよく理解しておらず、関数に渡していると思います。啓蒙主義?

ありがとうございます。

EDIT2:一方私はこの問題について少し噛んだし、次の質問に収束するようだ:C/C++は、暗黙のうちにconst intへのポインタにintへのポインタに変換します。したがって、次の作品:

func(const int a[]) // aquivalent: func(const int *a) 
{ ... } 

int main() 
{ 
    int b[10]; 
    func(b); 
    return 0; 
} 

しかし、C/C++は、暗黙的にn個const intの配列へのポインタへのn intの配列へのポインタを変換しません。 n intの配列は、暗黙的にn const intの配列に変換されます。暗黙的変換でのこの間接レベルはサポートされていません。以下は、(少なくともCで警告と)拒否されます。

func(const int a[][n]) // aquivalent: func(const int (*a)[n]) 
{ ... } 

int main() 
{ 
    int b[m][n]; 
    func(b); 
    return 0; 
} 

それは、C++が暗黙のうちにもできるかどうかタイプBのテンプレートにタイプAのテンプレートを変換しない問題に似ています暗黙的にBに変換されます.2つのテンプレートは完全に異なるタイプです。

これは正しい答えですか?

+0

申し訳ありませんが、私はまだコンパイラがこの場合に警告をスローする理由はありませんでした。何か案は? – phlipsy

答えて

1

あなただけFUNCの呼び出しで引数をキャストして互換性のある値を渡す、CONSTを排除する必要はありません。

 
    func((void *)i); 

可能ならば、CONSTとして私を宣言するpreferrableことが、このうハックはうまくいくはずです。

+1

'(void *)'へのキャストは醜いです...なぜconstにキャストするだけでいいのですか? 'func(const int(*)[3])i);' –

+1

見た目は見た目にあります。私は明示的なキャストがより安全であることに同意しますが、void *キャストは読みやすいと思っています。いずれにせよ、私がconstであると宣言する方が良いです。 –

+0

解決策に加えて、私は「なぜ」に興味があります。なぜ、配列のintが単純にconst intの配列に変換できるかをコンパイラが見ることができないのです。元の質問でも私の更新をお読みください。 – phlipsy

2

i変数は3要素の配列です。

関数に関数を渡すと、関数内で最初の要素へのポインタになります。コンパイラはconstをポインターまたは指されたものに追加できます:3の整数の配列。しかし、から3つの整数の配列にからの配列を指すものを変更することはできません。

あなたはキャストを自分で行う必要があると思います。

#include <stdio.h> 

typedef const int array_of_3_constants[3]; 

void func(int (* const i)[3]) { 
    ++i[0][0]; 
    printf("Value: %d\n", i[1][1]); 
} 

void gunc(array_of_3_constants *i) { 
    ++i[0][0];        /* error */ 
    printf("Value: %d\n", i[1][1]); 
} 

int main(void) { 
    int i[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}; 
    func(i); 
    func((array_of_3_constants*)i);   /* warning */ 
    gunc(i);        /* warning */ 
    gunc((array_of_3_constants*)i); 
    return 0; 
} 
+0

コンパイラが3つの整数の配列を3つの定数の配列に変更できないのはなぜですか?それは傷つけないのですか? – phlipsy

+1

http://web.torek.net/torek/c/expr.htmlを読んでください。特に "The Rule"について言及している部分 – pmg

+0

私は自分の質問を編集しました。引用した記事の結果が正しいことを理解しましたか? – phlipsy

関連する問題