• ベストアンサー

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宣言は何処にいくんですかね・・・ ヒープじゃない予備領域とかあるんですかね・・・

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

> 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の場合でもいったんディスクからメインメモリに展開することになります。

その他の回答 (3)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.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) {  ... } のように、型名が非常に長くなる傾向にありますので、修飾子は後ろに付けるようにしないと、見辛くて仕方ありません。

  • crew21
  • ベストアンサー率26% (58/222)
回答No.3

細かなことはNo1,No2さんが書かれていて正しいと思うので、これ以上は省くけど、 15年以上Cでプログラミングしてきましたが、仮に文法的に正しいとしても、int const i てのは見た記憶ないですよ。 やっぱ const int i じゃないっすか。 そっちの方が、int i は const(変更不可)なんだぞ! というプログラマの意志が伝わってきますし。(少なくとも私はそう感じます) それに複数の const の変数があった場合、 const int i; const char a; ... の方が、constが揃っていて、パッと見で見やすくないですか。 ああ、この変数一群は全部 const なんだなと把握しやすいですよ。

  • kary
  • ベストアンサー率55% (10/18)
回答No.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をおいて、例外的に先頭のみ前に置くことができる」と覚えると混乱しないようです。また、常に後ろにつけるという方法もあると思います。

関連するQ&A

  • 関数内でconst修飾子を使用した場合の配置

    お世話になります 関数内でconst修飾子を付加した領域を宣言します。 その領域は何処に取られるのでしょうか? RAM?ROM?スタック? コンパイル環境により異なるのでしょうか? void Test(void) { const int i_dat = 0;   ・・・・・・ } よろしくおねがいいたします。

  • (int *)の意味

    しょーもない質問すみません。 C++を独学中のプログラミング自体初学者です。 今読んでる教科書に、malloc関数の説明として、 指定された大きさの領域をヒープに割り当て、その領域の先頭のポインタを返す関数であるとあり、 例には、 .... int *x; x=(int *)malloc(sizeof(int)); *x=100; ..... などとあるのですが、malloc関数の前の(int *)は xはあくまで変数、malloc関数で帰ってくるのはpointerなので、 *でポインタから変数にした上で、その変数の型をintに強制的にしているという理解で合っているでしょうか?? どうも*がついている分、xはポインタのような気もして、混乱しています。

  • C++で、メンバもヒープに確保されていますか

    C++でどこまでヒープに確保されるのかが分からなくなる場合があります。 特に、配列がある場合や、クラスを使う場合newしてインスタンス作って使用する場合と、 そうでない場合があり、どこまでヒープ領域に確保されているのか 分からなくなってしまっています。 (開発環境 Visual Studio 2013等) Q1 クラス内の配列 class AA{ public: int x; int dat[10]; }; AA *a0 = new AA(); とする場合と AA a1; とする場合。 このとき、メンバ変数はそれぞれ、 a0->xはヒープ領域に確保 a1.xはスタック領域に確保 されるという理解で良いですか? そして、配列a0->dat[0]等 もヒープ領域に確保されていますか? Q2 クラス内にクラス class BB{ int u,v; AA aa; }; BB *b0 = new BB(); とした場合、 b0がヒープに確保されるとして、 b0->aaはヒープに確保されており、 b0->aa.xやb0->aa.dat[0]等もヒープに確保されているという ことで良いでしょうか? Q3 確認方法 変数等がヒープかスタック領域のどちらに確保されたかは どうやって見分けることができますか? アドレスの値から判断できますか? よろしくお願い致します。

  • constについて

    #include <iostream> using namespace std; class I { int *x; public: unsigned int size; I(){size=0;x=new int[size];} I(unsigned int i){size=i;x=new int[size];} ~I(){delete []x;} int &operator()(unsigned int i){return x[i];}//!!!! const int &operator()(unsigned int i) const{return x[i];}//???? }; void main() { I a(10); for(int i=0;i<10;i++)a(i)=i;a(2)=a(0); for(int i=0;i<10;i++)cout<<a(i); } この場合は//????はいらないと思いますが //????を定義することがありますがどんな場合でしょう //!!!!があるのにあったほうがいいのはどんな場合でしょう?

  • volatile修飾について

    組み込み系等でよく用いられる、volatile修飾子について質問させてください。 たまに、"volatile const int aaa" などと宣言された変数を見かけることがあります。 volatileやconstの意味はわかっているつもりですが、"const int aaa"ではなく、"volatile const int aaa"と宣言しなくてならないケースというのは、どういった場合があるのでしょうか? 具体的なコードで例を示していただけると助かります。 以上、よろしくお願いします。

  • ヘッダーファイル内でconst変数を初期化する時にエラー

    ヘッダーファイル内でconst変数を初期化する場合、 以下のようにしているのですが、エラーが出てしまいます。 どのようにすればうまくいくのでしょうか? 環境はVisualC++.NETです。 class abc{ private:  const int x; public:  abc(){   x = 10;  } }

  • C言語におけるポインターとconstの関係について

    C言語について質問があります。 1. int **p; const int **p1 = p; //型に互換性がないという警告 2. int *p; const int *p1 = p; //OK 上記2パターンありますが、なぜ1のパターンだと警告がでて、2のパターンだと警告が出ないのでしょうか? コンパイラはgccの4系列と3系列で試してみましたが同じ結果になりました。 constで修飾されていても、変数の内容を変更できるかできないかだけで、型情報には影響を与えないと考えておりましたが、実際に警告がでてしまい、疑問に思っております どなたか分かる人がいましたら教えていただけないでしょうか?

  • static constメンバ変数(配列)の初期化について

    C++初心者です。 constメンバ変数の初期化について教えてください。 クラスの中に、static constメンバ変数(配列)を持ちたいのですが、 <コード1> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2] = {1, 2}; }; とすると、VC++ 2005では、 error C2059: 構文エラー : '{' error C2334: '{' の前に予期しないトークンがありました。関数の本体は無視されます というエラーが発生します。 何がいけないのでしょうか? また、下の様にするとOKでした。 <コード2> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2]; }; const int hoge::fuga[2] = {1,2}; こうすればコンパイルが通る事は分かったのですが、なぜこんな面倒な事をしないといけないのかが分かりません。 コード1では何がいけないのでしょうか? 以上、よろしくお願いします。

  • C++ の new演算子について

    C++ の new演算子について質問です。 new演算子を用いてクラスのインスタンスを作ったときに、 クラスのメンバー関数内で使用される自動変数はメモリの何処に割り付けられますか? 以下の回答の内のいずれかと想定しています。 ・ヒープ領域 ・スタック領域 たとえば、以下のように、クラスTestClassが定義されていたとします。 class TestClass { int x; // int型(4byteとする) char y; // char型(1byte) long z; // long型(4byte) void play(short); } void main(void){ TestClass* pt = new a(); play(10); } void TestClass:: play(short n){ char a; long b; static c; for(int a = 0; a < 10; a++ ){ b = n * a; cout << b; } } main関数内で、インスタンスを作成した時点で ・TestClassのデータメンバx,y,z ⇒ ヒープ領域に確保(4+1+4 = 9byte。もしかしたらアライメント     の関係で もう少し大きく領域を確保するかも) ・play関数で使われる変数n,a,bの領域は何処に確保されるのでしょうか? 変数cは静的変数用領域に保存される? new演算子で作ったインスタンスはdelete演算子を使わないと消えないと勉強しました。(OSが消さない限り) つまり、上記ではmain関数を抜けても、変数x,y,z,n,a,bの実体は残ると考えてよいのでしょうか? そう考えると、n,a,bの実体はスタックではなく、ヒープ領域に確保する気がします、、 どうか、ご教授ください。

  • 可変引数をconstで参照渡し

    以下のようなクラスをconstの参照渡しでうけとる、可変引数を持つ関数を作りたいのですが、以下のようにしてもうまくいきません。 何か良い方法はないものでしょうか? template<class TT> class vector3{ public:  enum{NUM=3};  TT x[NUM];  void Sum(const int num,...); }; template<class TT> void vector3<TT>::Sum(const int num,const ...){  int i,j;  va_list list;  va_start(list,num);  for(i=0;i<NUM;i++){   x[i]=va_arg(list,&vector3<TT>).x[i];  }  for(j=1;j<num;j++){   for(i=0;i<NUM;i++){    x[i]+=va_arg(list,&vector3<TT>).x[i];   }  }  va_end(list); }

専門家に質問してみよう