こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

const int i ? int const i ?

お世話になります

初歩的な事ですがよろしくお願い致します
const 修飾子って変数型の前につけるの?後につけるの?

//----------------------------------------------------
const int iTest1[] = { 0x0000, 0x0000 };
const int iTest2[] = { 0xFFFF, 0xFFFF };

const int* const piTest[] = { iTest1, iTest2 };
//----------------------------------------------------

const int 型のポインタ配列をロム領域に確保したい場合は変数の後にconst修飾子をつけると思います

const const int* piTest[] = { iTest1, iTest2 };
これだとエラーとなるはずです。。。


そこで、疑問に思ったのが、私の書式だと、const intとconst修飾子は前に着けるのが普通だと思ってました
//----------------------------------------------------
  const int i = 0;
  int const i = 0;
//----------------------------------------------------
でも、どちらでもコンパイルは通ると思います
配置領域を確認した所、どちらもROMに確保されてました
一般的にどちらが正解なのでしょうか?


const const int* piTest[] = { iTest1, iTest2 };
が、エラーになるという事は、int const i が正解なのでしょうか?


教授よろしくお願い致します


ちなみに、組み込み系に特化した話になっています
windows系とかだとconst宣言は何処にいくんですかね・・・
ヒープじゃない予備領域とかあるんですかね・・・

投稿日時 - 2007-10-10 10:09:41

QNo.3416845

すぐに回答ほしいです

質問者が選んだベストアンサー

> const int* const piTest[] = { iTest1, iTest2 };

これは、

(const int*) const piTest ...

の意味ですね。(正しい文法ではカッコは付けられません)
piTestそのものを修飾するには、constは必ず後ろに付けなければなりません。

> const const int* piTest[] = { iTest1, iTest2 };
> これだとエラーとなるはずです。。。

C90ではエラーですが、C99ではエラーになりません。(警告は出るかもしれません)

実際のところ、どの構成要素を修飾するのかが明確であれば、修飾子は前でも後でも真ん中でもかまわないのです。

const unsigned int x;
unsigned int const;
unsigned const int x;

これらは、どれでもOKです。
もし、どの構成要素を修飾しているのかがよく分からないのであれば、修飾子は必ず後ろに付ける方が無難です。

> どちらもROMに確保されてました
> ちなみに、組み込み系に特化した話になっています

組込みでもPCでも関係ありません。
書き換え不可の静的オブジェクトをどこに配置するかは、リンカの設定で決まります。組込みでも、起動時にROMやフラッシュメモリからいったんRAMに展開することもあるように、PCの場合でもいったんディスクからメインメモリに展開することになります。

投稿日時 - 2007-10-10 11:16:01

ANo.1

このQ&Aは役に立ちましたか?

19人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

> constが揃っていて、パッと見で見やすくないですか。
> ああ、この変数一群は全部 const なんだなと把握しやすいですよ。

その考え方は危険だと思いますよ。

const int a;
const char *b;
int (* const c)(int);

を、その基準でパッと見で判断すると、間違いなく事実誤認につながります。
単純なものはconst intのようにすればよいと思いますが、よく見ずに、脊椎反射的に型を判断してしまうのは、やはりまずいのではないでしょうか。

ちなみにC++であれば、

template<class C, class Traits, class Allocator>
void func(std::basic_ostream<C, Traits>& ostr, std::basic_string<C, Traits, Allocator> const& str)
{
 ...
}

のように、型名が非常に長くなる傾向にありますので、修飾子は後ろに付けるようにしないと、見辛くて仕方ありません。

投稿日時 - 2007-10-11 12:53:00

ANo.3

細かなことはNo1,No2さんが書かれていて正しいと思うので、これ以上は省くけど、

15年以上Cでプログラミングしてきましたが、仮に文法的に正しいとしても、int const i てのは見た記憶ないですよ。
やっぱ const int i じゃないっすか。

そっちの方が、int i は const(変更不可)なんだぞ! というプログラマの意志が伝わってきますし。(少なくとも私はそう感じます)

それに複数の const の変数があった場合、
const int i;
const char a;
...
の方が、constが揃っていて、パッと見で見やすくないですか。
ああ、この変数一群は全部 const なんだなと把握しやすいですよ。

投稿日時 - 2007-10-11 11:02:41

ANo.2

constの位置について、「C言語ポインタ完全制覇」という書籍に詳しく書かれています。これによると、constはその直後にあるものを修飾するとの事です。具体的には、
int const foo;
ではfooがconstになるので、fooの値が変えられません。また、
int * const foo;
ではfooがconstになるので、
*foo = 100;
はOKだけど
int x;
foo = &x;
はNGになります。
int const * foo;
では*fooがconstですので、int * const fooの場合と逆になり、
*foo = 100;
がNGになります。さらに、両方をconstにするには
int const * const foo;
になります。ここで、ややこしいことに、先頭のみ(この例ではint)例外的にconstの位置を入れ替えて、
const int foo;

const int * const foo;
とすることができるとのことです。つまり、「基本的には後ろにconstをおいて、例外的に先頭のみ前に置くことができる」と覚えると混乱しないようです。また、常に後ろにつけるという方法もあると思います。

投稿日時 - 2007-10-10 20:51:54

あなたにオススメの質問