E05200029:Expected an expression. のエラーについて質問があります。
使用マイコン:RX64M開発環境:e2studioコンパイラ:CC-RX V3.00
現在ヘッダファイルに下記のマクロ定義と、
C言語の文法として配列を丸ごと代入することができません。あとbuf1[NUM_BYTE]はbuf1配列のNUM_BYTEで指定された位置の格納位置を意味しています。おそらく呼び出しものがNUM_BYTEの配列だと思います。でも、配列で確保した範囲でアクセスできるのはN要素なら0からN-1です。これは代入に間違いがありますし、範囲外のエリアへのアクセスになります。それからNUM_BYTEというのは気持ちが悪いのでNUM_COUNTSみたいなのの方がいいかと思います。intはバイトじゃないですから。もし配列まるごと値セットしたいなら、下のような記述になります。
マクロはC言語処理系ではCコンパイラの前処理ソフトで処理されます。ファイルで一度定義されるとファイル終端まで#undefで無効化されるまで有効です。#include <ファイル名>をよく使うと思いますが、これはソースコードに#includeで指定したファイルを文字通り含んだ状態にしてしまいます。やろうと思えば#includeで.cファイルを指定しても問題ないわけです。
わわいです
defineの定義やらスコープとは全く関係ありません。
> buf1[NUM_BYTE] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
Yamamoto様
ご回答ありがとうございます。そもそも要素の指定ができていなかったですね。forループで配列をコピーするやり方に変更し、配列がコピーされているのは確認できましたが、やはり配列の代入方法が間違っていたみたいです。ご指摘の通り要素数の指定も間違いですね。また、case1文の中身を{}でスコープしていることについては、switch文の理解不足でした。{}でくくらなければswitch文全体にスコープされてしまいますね。「static const int data_table[]」とする書き方は大変勉強になりました。この書き方だと不用意に書き換えられることも防げるのでまねさせていただきます。memcpyを使うとforループでの代入に比べて、コード量が減りますね。自分のforループで代入するやり方はコード量が多く見づらいので、参考にさせていただきます。実際にプログラムを動かし、配列に格納されていることが確認できました。ありがとうございました。#defineについて今一度理解しました。
わわい様
規格に沿っていないだけでした。(初心者にはこんな程度でも「だけ」ではない大事になってしまします..。)
んで、スコープに関して、ですが、中括弧 { } が重要となります
いくつかの例外はありますが、変数を定義した場合、その変数は、定義した行以降、定義した中括弧の中、のみが有効となります。
グローバル変数なんかは、すべてのカッコの外側で定義されるために、(そのソースの)全体がスコープとなります
今回特にswitch文の中でのスコープの仕方について問題がありました。エラーが起きていた原因としては、書き方の問題がそもそもありましたが、Yamamoto様の回答をお借りすると、「static const int data_table[]」は{}スコープの中にあることで、スコープされている変数はコンパイルされるけれども、スコープされていない場合には対象外になってしまうからでしょうか。switch文の外で定義した変数(例えば int = a; )をcase文の中で使用する場合( a = 1;)には{}が必要ないですよね。別の書き方としては、
switch(data){
int a;
case1:
a = 1;
break;
}
が許されるので、配列についても使用する配列を共通化する場合には、
と書くことで、関数が実行されるたびに場合分けで配列の中身がその都度コピーされるようになりますね。
こう見ると、使用する配列を共通化する/しない が判断基準でしょうか。
その書き方だと、switch文を抜けるとdata_tableは消滅してしまいますが、そんでいいのん?ってはなしになりますが。
で、それでいいなら、その配列の定義はcase 1 の直後に持ってくる方がわかりやすいですね。
まあしかし、そういう用途なら、ローカル変数とせずに、const付きのグローバル変数にしてしまうのが一般的だと思います。
現在の用途的にはdata_tableはbuf1、buf2にコピーしているので、消えても問題ないかなとは思っています。変わらない値であれば、const付のグローバル変数で初期化してあるものを使うのが確かに良いですね。大変勉強になりました。ありがとうございます。
んで、ここでなんでconst付きのグローバル変数がいいか、ってのを説明しときます
この手のマイコン用のC言語の処理系では(もちろん例外もありますが)
const付きのグローバル変数にしとけば、それは定数とみなされてROM領域にそのデータが展開されます。
こうなると、この変数の使用に際し、スタックは消費されませんし、コードの実行時のコストにはなりません
ローカル変数だと、その初期化に実行時間がかかってしまうことになります