- ベストアンサー
dequeue(BYTE *x)関数の戻り値について
以前、キューに関する質問をさせていただいた時に、回答者の方から、 BYTE dequeue(void) { BYTE x; if(Head==Tail){ QueueState = QSTATE_EMPTY; return; } Head=(Head+1)%MAX_BUF_NUM; x=UartSendBuf[Head]; UartSendBuf[Head]=0x00; //出力し終わったら0x00でクリアしておく。 return x; } 私のdequeue関数でエラーが発生している場合に単なる”return”で戻しているということでご指摘頂いたのですが、下記する文章で回答者の方が教えて頂いた内容で理解できない部分があり、困っております。 ----(回答者さんの文章)------------------------------------- その他、気づいた点。dequeue()はBYTE型の値を返す関数なのに、異常時に単にreturn;してます。こういう事をしてると後で痛い目に遭います(笑)。 このようなケースでは次のどちらかの方法をとります。 (a)正常時には決して返すことの無い値(0とか-1など)をエラーとして返す。 しかし表現可能なすべての値がデータとしてありうる場合はこの方法をとれないので、 (b)関数が返す値を成功か失敗か(或いはエラーの種類)だけにする。 データを返すためのポインタを引数として渡してもらい、例えば int dequeue(BYTE *x) として、*x = UartSendBuf[Head]; でデータを返します。 -------------------------------------------------------------- 確かにコンパイラはreturnだけで返すのはまずいとワーニングを出しているので、作り変えてみたのですが、 BYTE dequeue(BYTE *x) { if(Head==Tail){ QueueState = QSTATE_EMPTY; return 0xFF; } Head=(Head+1)%MAX_BUF_NUM; *x=UartSendBuf[Head]; return *x; } このポインタ変数が入ってくるのがよくわからず困っています。*xがreturnとなっていますが、どのような戻り値が返ってくるのでしょうか? あと、この関数を使う場合、 dequeue(Head); このような引数を入れてあげればよいのでしょうか? また、キューからデータを取り出したい場合は、 testBuf[i]=UartSendBuf[Head]; test = dequeue(Head); このようにdequeue関数の前でデータを取り出してから、dequeue関数の戻り値で判定するという処理をするようにしなければいけないでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
作り変えたdequeue関数をぱっとみただけでも、戻り値と引数の2つで値を返しているように見えます。おそらく(a)と(b)の内容をごちゃ混ぜにしてしまっているのだと推測します。 (a)にならって書くのならば以下のような感じだと思います。 BYTE dequeue(void) { BYTE x; if(Head==Tail){ QueueState = QSTATE_EMPTY; return 0xFF; } Head=(Head+1)%MAX_BUF_NUM; x=UartSendBuf[Head]; UartSendBuf[Head]=0x00; //出力し終わったら0x00でクリアしておく。 QueueState = QSTATE_VALID; return x; } // 呼び元 BYTE x; x = dequeue(); // xが0xFFかどうかで成否判断 (b)にならって書くのならば以下のような感じだと思います。 (QueueStateの型がわからないのでint型と仮定) int dequeue(BYTE *x) { if(Head==Tail){ *x=0xFF; return QSTATE_EMPTY; } Head=(Head+1)%MAX_BUF_NUM; *x=UartSendBuf[Head]; return QSTATE_VALID; } // 呼び元 BYTE x; QueueState = dequeue(&x); // QueueStateがQSTATE_VALIDかどうかで成否判断 >このポインタ変数が入ってくるのがよくわからず困っています。*xがreturnとなっていますが、どのような戻り値が返ってくるのでしょうか? この疑問が出てくるということは、まだポインタについて理解ができていないのだと思います。そのあたりをしっかり理解されたほうが後々ためになるでしょう。 最後に、前回の質問を締め切らずに質問を繰り返すのはマナー違反です。気をつけましょう。
その他の回答 (2)
- Tacosan
- ベストアンサー率23% (3656/15482)
「以前、キューに関する質問をさせていただいた時」の「以前の質問」がどれかは分かりませんが, もともと回答では int dequeue(BYTE *x) となっているはずなのになぜあなたは BYTE dequeue(BYTE *x) のように作り変えたのでしょうか? (b) では親切にも「関数が返す値を成功か失敗か(或いはエラーの種類)だけにする。データを返すためのポインタを引数として渡してもらい~」と書かれていますよね. 返り値は「この関数が成功したか失敗したか」のみを伝えるために使うのですよ.
お礼
回答頂きありがとうございました。 >「以前、キューに関する質問をさせていただいた時」の「以前の質 > 問」がどれかは分かりませんが, もともと回答では > int dequeue(BYTE *x) > となっているはずなのになぜあなたは > BYTE dequeue(BYTE *x) > のように作り変えたのでしょうか? 確かに、BYTEの宣言ではなくて勧められた時はintでの宣言ですね。私の勉強不足だと思うのですが、なぜ戻り値の型がBYTE(8ビット変数)ではなくてint(16ビット変数)なんですか? すみません教えてください。
補足
以前キューに関しての質問というのはこのページになります。 http://dell-support.okwave.jp/qa5486873.html
- asuncion
- ベストアンサー率33% (2127/6289)
>*xがreturnとなっていますが、どのような戻り値が返ってくるのでしょうか? xは、BYTE型のポインタ変数ですね。 したがって、*xは、xが指しているBYTE型の値です。 >dequeue(Head); >このような引数を入れてあげればよいのでしょうか? Headの型が不明であるため、正しいとも間違っているとも答えられません。 >dequeue関数の前でデータを取り出してから dequeue関数「そのもの」が、データを取り出す役目を持っているのではありませんか?
お礼
回答頂きありがとうございます。 私の質問の内容を自分で読み直したのですが、自分でも何を質問しているかわからないほどへんな文章になっており大変ご迷惑をおかけしております。 以前dequeue関数などのキューに関する質問した際に勧められた BYTE dequeue(BYTE *x) { if(Head==Tail){ QueueState = QSTATE_EMPTY; return 0xFF; } Head=(Head+1)%MAX_BUF_NUM; *x=UartSendBuf[Head]; return *x; } この関数で、私が疑問に感じているのが、この関数の機能はどのようなものかがよくわからないという感じです。 この関数の機能はどのようなものなのでしょうか? たぶんですが、勧めて頂いた方が ”(b)関数が返す値を成功か失敗か(或いはエラーの種類)だけにする。” ということをおっしゃっていたので、たぶんdequeue関数を実行すると、 ”戻り値としてUartSendBuf配列変数にキューされているデータを取り出して、Head変数をインクリメント” ではなく、 ”戻り値として、UartSendBuf配列変数の配列番号(これってポインタ番号っていうのが正しいんでしたっけ?)を返す。エラーの場合はあり得ない配列番号0xffを返す” ということがこの関数の機能の狙いなんでしょうか? >Headの型が不明であるため、正しいとも間違っているとも答えられません。 宣言は BYTE Head=0; BYTE Tail=0; としています。 また、配列変数は BYTE UartSendBuf[24]; と宣言しています。 MAX_BUF_NUMは#defineで24の別名です。 たとえばですが、 Head=5,Tail=8だった場合、 test = dequeue(Head); これを実行した場合、testに代入される数値は何になるのですか?
補足
補足させていただきたいのですが、特に理解ができないのが、 *x=UartSendBuf[Head]; このプログラムです。*xに代入される場合xにはどのような数値が代入されるのでしょうか?
お礼
回答頂きありがとうございます。 いろいろな質問をさせて頂くなかで、自分がポインタについての知識が乏しいことを再認識しました。 ポインタを今回はぜひ使ってみたいと思いぐぐっていたら、 http://www9.plala.or.jp/sgwr-t/c/sec10.html このページを見つけて、回答者のかたのプログラムの内容がわかりました。 引数に設定する変数のアドレスは、dequeue関数実行時に、 ”*x=UartSendBuf[Head];”ここで得られるデータを代入するアドレスを決めていたんですね!! 関数の戻り値は1つしか取得できないけど、このやり方ならば関数実行後に複数の結果データを取得することが可能になるんですね。だからポインタを使っていたんですね。かなり便利な気がしてきました。 すみません。追加で質問なんですが、このようなポインタの使い方は一般的なんでしょうか? ”*x=UartSendBuf[Head];”このプログラムの実行で*xのアドレスにデータが入ってくるのはわかったのですが、たとえばグローバル変数に代入させて、dequeue関数実行後、グローバル変数から、代入させたい変数にデータを移すということでも同じ結果になると思うのですが、ポインタを使った方が得な時というのはどのような状況になるのでしょうか? > 最後に、前回の質問を締め切らずに質問を繰り返すのはマナー違反です。気をつけましょう。 マナー違反ですね。以後気をつけます。