E05200029:Expected an expression. のエラーと#defineのスコープについて

E05200029:Expected an expression. のエラーについて質問があります。

使用マイコン:RX64M
開発環境:e2studio
コンパイラ:CC-RX V3.00

現在ヘッダファイルに下記のマクロ定義と、

#define NUM_BYTE 0x09
#define NUM1 0x01
#define NUM2 0x02
#define NUM3 0x03
#define NUM4 0x04
#define NUM5 0x05
#define NUM6 0x06
#define NUM7 0x07
#define NUM8 0x08
#define NUM9 0x09
ソースファイルに下記の関数を作りました。
void syori(int data, int *buf1 , int *buf2)
{
        switch (data)
        {
        case 1:
                buf1[NUM_BYTE] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
                buf2[NUM_BYTE] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
               
                break;
       
   /*~その他case文~*/
        default:
                break;
        }

}
 
この中で、配列の要素をマクロ定義した定数で初期化しようとすると、E05200029エラーで「式がありません」となります。
プログラムを書いている最中でも、「Ctrl+spaceキー」で buf1[NUM_BYTE] = {};の波かっこの中で補完機能を使おうとしても、
そこでだけは「デフォルトの候補がありません」と表示されます。
原因は分かりますでしょうか。
#defineはマクロ定義なので、スコープなどないと考えていたのですが、そのあたり自分だけの調査で限界が来たので、教えていただければと思います。
Parents
  • わわいです

    defineの定義やらスコープとは全く関係ありません。

    buf1[NUM_BYTE] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};

    > buf2[NUM_BYTE] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
    これらの行の記述がC言語として不当なもの、なのでそのエラーが出ているだけですね
  • わわい様

    規格に沿っていないだけでした。(初心者にはこんな程度でも「だけ」ではない大事になってしまします..。)

  • わわいです

    んで、スコープに関して、ですが、中括弧 { } が重要となります

    いくつかの例外はありますが、変数を定義した場合、その変数は、定義した行以降、定義した中括弧の中、のみが有効となります。

    グローバル変数なんかは、すべてのカッコの外側で定義されるために、(そのソースの)全体がスコープとなります

  • わわい様

    今回特にswitch文の中でのスコープの仕方について問題がありました。
    エラーが起きていた原因としては、書き方の問題がそもそもありましたが、Yamamoto様の回答をお借りすると、「static const int data_table[]」は{}スコープの中にあることで、スコープされている変数はコンパイルされるけれども、スコープされていない場合には対象外になってしまうからでしょうか。switch文の外で定義した変数(例えば int = a; )をcase文の中で使用する場合(  a = 1;)には{}が必要ないですよね。
    別の書き方としては、

    switch(data){

      int a;

    case1:

          a = 1;

        break;

    }

    が許されるので、配列についても使用する配列を共通化する場合には、

    void syori(int data, int *buf1 , int *buf2)
    {
            switch (data)
            {
                    int data_table[NUM_BYTE];  
            case 1:
           
                     data_table[0] = NUM1;
                     data_table[1] = NUM2;
                     data_table[2] = NUM3;
                     data_table[3] = NUM4;
                     data_table[4] = NUM5;
                     data_table[5] = NUM6;
                     data_table[6] = NUM7;
                     data_table[7] = NUM8;
                     data_table[8] = NUM9;
                   
                    //data_table[] = {NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9};
                    memcpy(buf1, data_table, sizeof(data_table));
                    memcpy(buf2, data_table, sizeof(data_table));

                    break;
           
            default:
                    break;
            }

    }

    と書くことで、関数が実行されるたびに場合分けで配列の中身がその都度コピーされるようになりますね。

    こう見ると、使用する配列を共通化する/しない が判断基準でしょうか。

  • わわいです

    その書き方だと、switch文を抜けるとdata_tableは消滅してしまいますが、そんでいいのん?ってはなしになりますが。

    で、それでいいなら、その配列の定義はcase 1 の直後に持ってくる方がわかりやすいですね。

    まあしかし、そういう用途なら、ローカル変数とせずに、const付きのグローバル変数にしてしまうのが一般的だと思います。

  • わわい様

    現在の用途的にはdata_tableはbuf1、buf2にコピーしているので、消えても問題ないかなとは思っています。変わらない値であれば、const付のグローバル変数で初期化してあるものを使うのが確かに良いですね。大変勉強になりました。ありがとうございます。

  • わわいです

    んで、ここでなんでconst付きのグローバル変数がいいか、ってのを説明しときます

    この手のマイコン用のC言語の処理系では(もちろん例外もありますが)

    const付きのグローバル変数にしとけば、それは定数とみなされてROM領域にそのデータが展開されます。

    こうなると、この変数の使用に際し、スタックは消費されませんし、コードの実行時のコストにはなりません

    ローカル変数だと、その初期化に実行時間がかかってしまうことになります

Reply
  • わわいです

    んで、ここでなんでconst付きのグローバル変数がいいか、ってのを説明しときます

    この手のマイコン用のC言語の処理系では(もちろん例外もありますが)

    const付きのグローバル変数にしとけば、それは定数とみなされてROM領域にそのデータが展開されます。

    こうなると、この変数の使用に際し、スタックは消費されませんし、コードの実行時のコストにはなりません

    ローカル変数だと、その初期化に実行時間がかかってしまうことになります

Children
  • わわい様

    単純に変わらないから、という事ではなく、実行時間に関わってしまうのですね。いよいよもってコード全体の見直しが必要になりそうです...。詳細にありがとうございます。