HEWとRX621で、コンパイルしています。
ローカル変数を「const」にすると、スタック領域に配置されます。
関数の最初で、定数をスタック領域にコピーするプログラムが書かれています。
「const static」にすれば、定数のセクションに配置されます。
「const」は定数で書き込めないんだから、スタック領域に書き込むのはおかしいと思うのですが。
> const char a[] = "A";> の宣言だと、aには代入できないですね。
代入でなく初期値なので問題ありません。
4っつ前の書き込みは、分かり易いように編集してあります。
試験したときの文字列はもっと長いので、転送バイト数のカウンタ値に食い違いが出ます。
要点は、このようなコピー命令が入っている事の証明です。
fujitaさん
> 代入でなく初期値なので問題ありません。はい、これも私の書き方が悪かったですが、const char a[] = "A"; の書き方では、aはconst変数です(初期化が必要)。この書き方を、const char* a = "A"; と同じだと勘違いしていたという意味です。この場合は、非constで、初期化はなくてもよいです。const char* const a = "A"; はconst変数で初期化が必要ですね(=最初の書き方)
リカルドさん要点は理解しています。結局、ローカル変数については、最適化の問題かなと思ってまして、リカルドさんの実験結果は面白かったです。最適化されれば使っていない変数は削除されたりするわけで、C言語の宣言と配置は一対一にならないのかな、と(今なったとしても、コンパイラのバージョンで変わるとか)。あまり時間使えてませんが、マニュアルになにか保証される記述が無いかなーと思って、見てるんですけど、見つけられないです。
constなauto変数って考えたことがなかったですが、この結果は新鮮ですね。
でもconst修飾子は定数という意味だけだし、static修飾子は静的という意味だけ。
定数=ROMという考えは我々の経験則であって、コンパイラの定義ではないような気もします。
関数内でstatic無し(自動変数、動的配置)と言っている時点でstackに積まれるのは理に適っているかな?とも思います。
どちらかと言うと、auto変数のconstに代入しようとしたとき、コンパイラエラーがちゃんと出るのかそっちのほうが気になります。
いろいろ気になってます (^^;autoなconstへの代入は、エラーになりますよ。言語仕様ですね。constつけれるところは、つけて得することはあっても、損することはないはずです。
「定数」っていう言葉については、先日書いた通り、const int a = 1;とconst int cached_result = Func(x);は意味が違いますよね。
前者は常に定値ですが、後者は編集不可のキャッシュ値みたいな意味で、xの値が変われば、その行を通った時のcached_resultの値は変わります。
コンパイラにとっては、ローカル変数の場合、const int a = 1;とstatic const int a = 1;は上記の前者の意味ならまったく同じですよね(ガンガン最適化されるでしょう)。
> const char a[] = "A"; の書き方では、aはconst変数です(初期化が必要)。
aは配列名であり変数ではありません。要素数を省略しなければ初期化も必須ではありません。
> const char* const a = "A"; はconst変数で初期化が必要ですね(=最初の書き方)
この場合も初期化は必須ではありません。const なので値の変更ができないだけです。
> コンパイラにとっては、ローカル変数の場合、
> const int a = 1;
> と
> static const int a = 1;
> は上記の前者の意味ならまったく同じですよね(ガンガン最適化されるでしょう)。
auto 変数は個別のアドレスを持つので違います。
例えば以下のプログラムで hoge(0) と piyo(0) の結果は異なります。
#include <stdio.h> const int* hoge(int b) { const int a = 1; if (b == 1 || &a == hoge(1)) { return &a; } else { return NULL; } } const int* piyo(int b) { static const int a = 1; if (b == 1 || &a == piyo(1)) { return &a; } else { return NULL; } } int main(void) { printf("hoge(0) = %p\n", hoge(0)); printf("piyo(0) = %p\n", piyo(0)); return 0; }
付き合っていただいて、ありがとうございます
>> const char a[] = "A"; の書き方では、aはconst変数です(初期化が必要)。>> aは配列名であり変数ではありません。要素数を省略しなければ初期化も必須ではありません。>>> const char* const a = "A"; はconst変数で初期化が必要ですね(=最初の書き方)>> この場合も初期化は必須ではありません。const なので値の変更ができないだけです。
私の勉強不足で、配列名とconst変数の違いがわかりませんが、CC-RX最新バージョンで、
const char a[2];
はエラーE0520257です。
const char* const a;
>> コンパイラにとっては、ローカル変数の場合、>> const int a = 1;>> と>> static const int a = 1;>> は上記の前者の意味ならまったく同じですよね(ガンガン最適化されるでしょう)。>> auto 変数は個別のアドレスを持つので違います。
なるほど、これはよい覚え方ですね。勉強になりました。hoge()の内容は、テンポラリのアドレス返すので、使えないですが、反例としては理解しました。アドレスで外のスコープへ渡せることを考えずに、同じだと表現していました。piyo()の内容は、同じデータが2回配置されないように、文字列なんかでは私も使います。(環境によっては、定数の重複はビルド時にひとつにしてくれる機能があったりしますが、変更時に1個所さわるだけにしたいので)
> CC-RX最新バージョンで、 > > const char a[2]; > > はエラーE0520257です。 > > const char* const a; > > はエラーE0520257です。
CC-RX V2.04.01 にて下記のコードをコンパイルしたところ
void hogera(const char* a) { (void)a; } void hoge(void) { const char a[2]; hogera(a); } void piyo(void) { const char* const a; hogera(a); } void main(void) { hoge(); piyo(); }
警告は出ますがビルドは成功しました。ひょっとして C++ でコンパイルされてるとかではないですか? C と C++ では const の機能は全く異なります。
========== 全ビルドの開始(2016年4月18日 13:27:48) ========== ------ ビルド開始(test, DefaultBuild) ------ >test.c W0511179:The evaluation version is valid for the remaining 13 days. test.c(14):W0520257:Const variable "a" requires an initializer >DefaultBuild\test.abs DefaultBuild\test.mot The evaluation period has expired. Renesas Optimizing Linker Completed ------ ビルド終了(エラー:0個, 警告:2個)(test, DefaultBuild) ------ ========== 終了しました(成功:1プロジェクト, 失敗:0プロジェクト)(2016年4月18日 13:27:53) ==========