• ベストアンサー

記述の意味がわからないdefine文

今、H8S2368というマイコンでOSをのせたプログラムに関して勉強中で、OSで動かすタスクの作り方をやっているのですが、どうやらプログラムを見てみると、 CAEATE_TASK(Net ,TASK_NET_STK_SIZE ,TASK_NET_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); この関数を実行することでタスクが作成されるようなのですが、 この”CAEATE_TASK”という関数を全ソースに検索してみたところ #define CAEATE_TASK(task,stack_size,prio,opt) \ strcpy(TaskUserData[id##task].TaskName, "##task");\ TaskUserData[id##task].TaskPrio = prio;\ OSTaskCreateExt(Task##task, (void *)0, &StackTask##task[stack_size-1], prio,\ id##task, &StackTask##task[ このように記述されていました。ちょっと今までのdefine文では見たことが無い記述がいっぱいあるのですが、これはどのような意味なのでしょうか?

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

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

#2です。 "##task"は"Net"にはなりません。 マクロ仮引数taskに対応する実引数がNetの場合、これを"Net"に展開するには、"##task"ではなく#taskとする必要があります。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

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

基本的にはすでに回答が出ているとおりです。 ただ、 "##task"という部分だけは、このマクロ定義のバグか、処理系にバグがあるための対策か、そのどちらかだと思います。

techhouse
質問者

お礼

回答頂きありがとうございました。​http://wisdom.sakura.ne.jp/programming/c/c42.html​​ このサイトを紹介して頂きありがとうございます。 見てみたところ、”トークン連結演算子”というのに該当するようですね。それで、今回質問に出した CAEATE_TASK(Net ,TASK_NET_STK_SIZE ,TASK_NET_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); #define CAEATE_TASK(task,stack_size,prio,opt) \ strcpy(TaskUserData[id##task].TaskName, "##task");\ TaskUserData[id##task].TaskPrio = prio;\ OSTaskCreateExt(Task##task, (void *)0, &StackTask##task[stack_size-1], prio,\ id##task, &StackTask##task[0], stack_size, &TaskUserData[id##task], opt); これがどのように読み変えられているのかを確認してみたところ、 #define TASK_NET_STK_SIZE 0x200 #define TASK_NET_PRIORITY 32 まずこれを踏まえておくと、結果として下記するようなことと同じということになるのでしょうか? #define CAEATE_TASK(task,0x200,32,0x00) \ strcpy(TaskUserData[idNet].TaskName, "Net");\ TaskUserData[idNet].Task32 = 32;\ OSTaskCreateExt(TaskNet, (void *)0, &StackTaskNet[0x200-1], 32,\ idNet, &StackTaskNet[0], 0x200, &TaskUserData[idNet], 0x00);

全文を見る
すると、全ての回答が全文表示されます。
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

id##taskのような表記は文字列連結ですね。 例えばtaskがNetのとき、id##taskはidNetになります。 # http://wisdom.sakura.ne.jp/programming/c/c42.html

techhouse
質問者

お礼

回答頂きありがとうございました。http://wisdom.sakura.ne.jp/programming/c/c42.html​ このサイトを紹介して頂きありがとうございます。 見てみたところ、”トークン連結演算子”というのに該当するようですね。それで、今回質問に出した CAEATE_TASK(Net ,TASK_NET_STK_SIZE ,TASK_NET_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); #define CAEATE_TASK(task,stack_size,prio,opt) \ strcpy(TaskUserData[id##task].TaskName, "##task");\ TaskUserData[id##task].TaskPrio = prio;\ OSTaskCreateExt(Task##task, (void *)0, &StackTask##task[stack_size-1], prio,\ id##task, &StackTask##task[0], stack_size, &TaskUserData[id##task], opt); これがどのように読み変えられているのかを確認してみたところ、 #define TASK_NET_STK_SIZE 0x200 #define TASK_NET_PRIORITY 32 まずこれを踏まえておくと、結果として下記するようなことと同じということになるのでしょうか? #define CAEATE_TASK(task,0x200,32,0x00) \ strcpy(TaskUserData[idNet].TaskName, "Net");\ TaskUserData[idNet].Task32 = 32;\ OSTaskCreateExt(TaskNet, (void *)0, &StackTaskNet[0x200-1], 32,\ idNet, &StackTaskNet[0], 0x200, &TaskUserData[idNet], 0x00);

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • RTOSのセマフォの使い方についての疑問

    今、H8S2368というマイコンを使って、RTOSのuCOSについて勉強しているところなのですが、RTOSがどのように動いているのかというのをイメージすることができなくて質問させていただきます。 たとえば、3つのタスクを宣言して、Swというタスクで、OscWaitというセマフォを使って、”OSSemPend(OscWait, 500, &err);”の500ミリ秒でタイムアウトが発生して、”OSSemPost(OscWait);”でセマフォを解除して、OscWaitで止まっていたOsc,Osc02のタスクを動かした場合、この場合、どのようにタスク内のプログラムは動きだすのでしょうか。 たぶんなのですが、Oscのタスクの方がプライオリティが高いので、こちらがまず動いて、while文で再度”OSSemPend(OscWait, 100, &err);”でOscWaitの信号が赤になって止まって、それから、Osc02のタスクが動き始めて、というのを繰り返すものと考えているのですが、そのように考えてよいのでしょうか? #define TASK_SW_ID 5 #define TASK_OSC_ID 6 #define TASK_OSC02_ID 7 #define TASK_SW_PRIORITY 30 #define TASK_OSC_PRIORITY 31 #define TASK_OSC02_PRIORITY 32 #define TASK_OSC_STK_SIZE 0x200 #define TASK_OSC02_STK_SIZE 0x200 #define TASK_SW_STK_SIZE 0x200 DECLARE_TASK(Sw,TASK_SW_STK_SIZE,TASK_SW_ID); DECLARE_TASK(Osc,TASK_OSC_STK_SIZE,TASK_OSC_ID); DECLARE_TASK(Osc02,TASK_OSC02_STK_SIZE,TASK_OSC02_ID); CAEATE_TASK(Sw ,TASK_SW_STK_SIZE ,TASK_SW_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); CAEATE_TASK(Osc ,TASK_OSC_STK_SIZE ,TASK_OSC_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); CAEATE_TASK(Osc02 ,TASK_OSC02_STK_SIZE ,TASK_OSC02_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); OS_EVENT *OscWaitt; DECLARE_TASK_FUNC(Sw) { BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 500, &err); OSSemPost(OscWait); } } DECLARE_TASK_FUNC(Osc) { BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp++; printf("OSC_temp %d \n\r",OSC_temp); } } DECLARE_TASK_FUNC(Osc02) { u16 cur,old; u8 OSC_temp02=0; BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp02++; printf("OSC_temp02 %d \n\r",OSC_temp02); } }

  • マクロ初級 #define

    #include <iostream.h> #define mkr(a) {cout << a;\cout << b;\} void main(void){ cout << "2数を表示するマクロ" << endl; mkr(1,9); } ↑これをコンパイルするとエラーになりました。 エラー 5行目 マクロ 'mkr' の呼び出しにおける引数の個数が 誤っている(関数 main() ) ネット上で見つけたものなんですが、このプログラムを 正しく修正するとどうなるんですか? マクロのソースを見たのは初めてだったので分かりませんでした。

  • UPDATE文のWHERE句にファンクション使いたい

    [OSのVER]:WindowsXP [OracleのVER]:9i UPDATE時にWHERE句に自作のユーザ関数を使いたいと思っていますが、 更新されずに困っています。 (エラーも出ません) 例) update TG_TBL set S_YMD = '20060601', LAST_UPDATE = SYSDATE , where ID_NO = '1401001' and CHK_SIK(ID_NO) in (1,2) ←使用したいチェック関数 ちなみに、以下のように同じ関数を使用すると1件のレコードが検索されます。 select * from TG_TBL where KANRI_NO = '1401001' and CHK_SIK(ID_NO) in (1,2) 関数部分をコメントアウトして、実行すると1件更新されます。 UPDATE文にユーザ関数を使用することはできないのでしょうか? 皆様のお知恵をお貸しください。 よろしく、お願いいたします。

  • スタックの配列プログラム

    スタックを配列で実現するプログラムとして #include<stdio.h> #define stack_size 100 #define stack_el_type int stack_el_type stack[stack_size]; int sp; void init_stack() { sp=-1 } void push(stack_el_type x) { if (sp < stack_size -1) stack[++sp] = x; else{ printf("stack full error.\n"); exit(1); } } stack_el_type pop() { if(sp >= 0 ) return stack[sp--]; else { printf("stack empty error.\n") exit(1); } } 上の完成形を参照として、 他の作り方として int stack[100] int sp void push(int x) int pop() を用いて作成する場合どのようにすればよいのでしょうか? またスタックを一方向リストで実現するプログラムを作成するとき struct node{ int data; struct node *next; } struct node *push(int x,struct node *root) struct node *pop(struct node *root) を用いて作成する場合どのようにすればよいのでしょうか? よろしければご教授お願いします

  • プログラムについて

    今スタっクのファイルから読み込んだ文字列をスタっクへプっシュしたりポっプしたりする過程がわかるプログラムを作ってます 。 作りかけのプログラムですがどこをどうすればいいか教えてください!! 一応コンパイルできます。 使ってない関数があるかもしれません。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUMBER 100 /*--- スタックを実現する構造体 ---*/ typedef struct { int max; /* スタックのサイズ */ int ptr; /* スタックポインタ */ char *stk; /* スタック(の先頭要素へのポインタ) */ } Stack; /*--- スタックの初期化 ---*/ int StackAlloc(Stack *s, int max) { s->ptr = 0; if ((s->stk = calloc(max, sizeof(int))) == NULL) { s->max = 0; /* 配列の確保に失敗 */ return (-1); } s->max = max; return (0); } /*--- スタックの後始末 ---*/ void StackFree(Stack *s) { if (s->stk != NULL) { free(s->stk); s->max = s->ptr = 0; } } /*--- スタックにデータをプッシュ ---*/ int StackPush(Stack *s, int x, int i,char *a[]) { if (s->ptr >= s->max) return (-1); if(x>=i) { puts("プッシュできる文字データはありません。"); return (-1); } strcpy(&s->stk[s->ptr++],&(*a)[x]); x++; return x; } /*--- スタックからデータをポップ ---*/ int StackPop(Stack *s, int x,char *a[]) { if (s->ptr <= 0) /* スタックは空 */ return (-1); strcpy(&s->stk[--s->ptr],&(*a)[x]); return (0); } /*--- スタックからデータをピーク ---*/ int StackPeek(const Stack *s, int *x) { if (s->ptr <= 0) /* スタックは空 */ return (-1); *x = s->stk[s->ptr - 1]; return (0); } /*--- スタックの大きさ ---*/ int StackSize(const Stack *s) { return (s->max); } /*--- スタックに積まれているデータ数 ---*/ int StackNo(const Stack *s) { return (s->ptr); } /*--- スタックは空か ---*/ int StackIsEmpty(const Stack *s) { return (s->ptr <= 0); } /*--- スタックは満杯か ---*/ int StackIsFull(const Stack *s) { return (s->ptr >= s->max); } /*--- スタックを空にする ---*/ void StackClear(Stack *s) { s->ptr = 0; } int main(void) { int i=0,j,ret,x=0; char *a[NUMBER]; char buffer[20]; FILE *fpin; Stack s; fpin=fopen("input2.txt","r"); //テキストファイルを読み取りモードで開く while(fgets(&buffer[0],sizeof(buffer),fpin) !=NULL ) { if(i>=NUMBER)//読み込む人数がNUMBERを超えてる時の処理 { puts("人数が100人を超えています"); goto END; } strcpy(&a[i][0],&buffer[0]); /*ret=sscanf(&buffer[0],"%s",&a[i][0]); //データ文字列を3分割 if(ret!=1) //1に分割できなかったときの処理 { puts("代入された入力項目の個数が3でありません"); goto END; }*/ i++; } for(j=0; j<i; j++) printf("%s\n",&(*a)[j]); if (StackAlloc(&s, 100) == -1) { puts("スタックの確保に失敗しました。"); return (1); } while (1) { int m; printf("現在のデータ数:%d/%d\n", StackNo(&s), StackSize(&s)); printf("(1) プッシュ (2) ポップ (0) 終了:"); scanf("%d", &m); if (m == 0) break; switch (m) { case 1: printf("データ:"); puts("こんちくしょ~"); if(StackPush(&s, x,i,&(*a)) == -1) puts("スタックへのプッシュに失敗しました。"); break; case 2: if(StackPop(&s, x,&(*a)) == -1) puts("ポップできません。"); else printf("ポップしたデータは%sです。\n", &s.stk[s.ptr]); break; } } StackFree(&s); END: fclose(fpin); return (0); }

  • strcpy(&... のような記述ができるのか

    現在C言語を習っている専門学校生です。 基本情報技術者を受けようと思い、以前に知り合いから貰ったアイテックの 予想問題集2005春をやっていましたが、その中に、 「単語を行末できれないように英文を出力する」という関数についての 問題がありましたが、 そこでstrcpy(&...という表現があり、ずっと勉強につかってきた「独習C 第3版」 ではこういう記述がなかったので、こういう記述は現実にあるのかどうか わからなく、ずっと悶々としておりましたが、いい加減に自己解決できそうになく、 今回投稿させていただきました。 以下がそのプログラムの一部を抜き出したものです。 #include <stdio.h> #include <string.h> #define BUFFMAX 1024 #define WORDMAX 16 void wordwrap (char str[], int max) { char word[BUFFMAX / 2][WORDMAX], buff[BUFFMAX]; int leng[BUFFMAX / 2], i, idx, cnt, pos; /*文字列を単語に分解する*/ ... /*出力する*/ ... i = pos = 0; while (i <= idx) { if ((pos + leng[i]) > max) { buff[pos - 1] = '\0'; printf("%s\n",buff); pos = 0; } strcpy(&buff[pos], word[i]);   ... } 事前にネットで「strcpy(&」で検索をしてみましたが、RSSリーダーを作るという記事(http://www.okisoft.co.jp/esc/tsu/make_rss_reader_7_003.html)でそれでも「strcpy( &(buf[i]), "月" );」などの表現はありましたが、疑問の解決には至らず、今はこの問題を作成した人が血迷っただけなのかな・・・とかしか考えていません。 どうかお時間のあるときで結構ですので、お答えいただければ幸いに思います。 どうかよろしくお願いいたします。

  • javaで name=id[?] を指定する方法とは?

    ショップ運営で、商品一覧から+-ボタンでそれぞれ数の増減をさせるよう、ほかのサイトを参考にして下記のようにjavascriptで記述してみました。 このうち、商品2と3はボタンが機能したのですが、商品1は数の増減ができません。 おそらく要素名に(name=id[1])と[]で囲っているからだと思うのですが、この[]を取らないまま、ボタンを機能させる方法はありますでしょうか? よろしくお願いします。 <FORM> 商品1:<INPUT type=text name=id[1] value=3 size=4> <INPUT type=button value="+" onClick="plus(this.form.id[1])"> <INPUT type=button value="-" onClick="minus(this.form.id[1])"> <BR> 商品2:<INPUT type=text name=id2 value=3 size=4> <INPUT type=button value="+" onClick="plus(this.form.id2)"> <INPUT type=button value="-" onClick="minus(this.form.id2)"> <BR> 商品3:<INPUT type=text name=id3 value=3 size=4> <INPUT type=button value="+" onClick="plus(this.form.id3)"> <INPUT type=button value="-" onClick="minus(this.form.id3)"> </FORM> <SCRIPT language="JavaScript"> <!-- function plus(chk){chk.value++; if (chk.value==6) {chk.value=5} } function minus(chk){chk.value--; if (chk.value==0) {chk.value=1} } // --> </SCRIPT>

  • SQL文の関数らしいのですが、意味を正確に調べたいとき。

    Visual Basic で組んだ業務ソフトのソースを見ているところなのですが…。データベースは SQL Serverを使っています。その中のコードとして SQL = "SELECT * FROM MPGSUB " _ & "WHERE 端末ID = " & Conv_DBValue(Client_ID, DB_String) というのがあります。これは、《"端末ID"列から、DB_Stringの型に変換した値をClient_ID という列名にして取得する》ということで良いのでしょうか。 Conv_DBValue やDB_String は、手元の辞典にも載っていないし、ネットで検索しても解説しているところがありません。このようなときは、プログラムで参照すべき他のモジュールが足りないと考えた方が良いのでしょうか。 ときどき調べがつかない関数があるので困ってしまうので、そのような時はどうすべきか教授願いたいです。(^^;

  • docomoで読み込み時のheader記述後のexitについて

    サンプルの挙動はPCでは書込み1回、Docomoでは書込み2回が行われます。 exitの前の#を取るとどちらも1回になります IF文中のheader:Locationでリロードを行い、再表示時にファイルに記録を行うというプログラムなのですが、header記述後の「exit;」を記載しない場合、プログラムが書き込みを2度行うという現象がおこり、理由について悩んでいます。 header:Locationでページを移動しているのに「exit;」を記載しない場合、初回読み込み時のheader後の処理が行われているのですが、 「header Location」というのは処理をストップさせる効果を必ずしも期待できないのでしょうか? <?php #リロード if(empty($_GET['id'])){ header("Location:./test.php?id=a"); #exit; } #記録 $read = id."\n"; file_put_contents("chk.txt",$read,LOCK_EX | FILE_APPEND); ?>

    • 締切済み
    • PHP
  • 関数が呼び出されるごとに文字列(IPアドレス)を格納したいのですが・・・

    こんばんは。 関数が呼び出されるごとに文字列(IPアドレス)を格納したいと思っているのですが、どのように記述すればよいか分かりません。 以下にプログラムを示します。 以下のプログラムは、int UDPReceive_IPaddr関数のwhileループ内のIPaddrstorage関数が呼び出されるたびに、IPaddrstorage関数内にて配列を用いて他の端末のIPアドレスを格納したいと考えています。 しかし、関数が毎回呼び出されるため、配列の記述の仕方に困っています。なにか解決方法はありますでしょうか? [プログラム] int UDPReceive_IPaddr(u_short portNo) { char IPaddr[16]; int size; //他の端末からIPアドレスをHELLO文字列(パケット)を受信することで知る。 while(1){ if(size == 5){ if(memcmp(recv_Buf,"HELLO",5) == 0){ strcpy(IPaddr,inet_ntoa(from.sin_addr)); IPaddrstorage(IPaddr); } } } int IPaddrstorage(char *IPaddr){ //配列を用いて、他の端末のIPアドレスを格納したいと考えています。 return 0; } よろしくお願いします。