以前、キュープログラムで”BYTE dequeue(BYTE *x)”というのを作成した際に、この作り方で質問させていただきい、この関数だと、
BYTE dequeue(BYTE *x)
{
if(Head==Tail){
if(QueueState != QSTATE_FULL){
return QSTATE_EMPTY;
}
}
*x=QBuf[Head];
Head=(Head+1)%MAX_BUF_NUM;
return QSTATE_VALID;
}
この関数だと、QueueState = dequeue(&UartSendBuf[i]);というように使用すれば、配列変数のUartSendBuf[i]でiの数値で指定した配列番号のメモリ番地にdequeueしたい値を入れることができ、なおかつ、キュープログラムがちゃんと動作したかのステータス値を戻り値として出力できるということを教わり、戻り値が複数出力できるような関数が作れるので大変便利だなぁと思ったのですが、
ちょっと疑問があるのですが、
QueueState = dequeue(UartSendBuf[i]);
というように&を付けずにこのプログラムを動かした場合、どのような動きをプログラムはしてしまうのでしょうか?
No.6ベストアンサー
- 回答日時:
>i = 8;
>QueueState = dequeue(UartSendBuf[i]);
>というようにしてこの関数を使ったとしても、以前の関数の動作と全く同じということになるということでしょうか?
コンパイルでエラーが起こるかどうかはそのコンパイラや書き方に依存するのでそこは軽く
ANSI C準拠で書いて対応コンパイラならエラーが出るでしょうし
K&R だっけ?でかいたらエラーは出ません
関数コール側の書き方が間違っているというのは変わりありません
( & を付けない以上ポインタを渡してません プログラムとしては期待する結果を得られません)
改造とかかれてますが
>x[0]=QBuf[Head];
のことでしょうか? そのコードであれば
*x=QBuf[Head];
と書いているのと同じですので結果は変わりません
例えがよくありませんが
住所と其処に住んでいる居住者の関係をイメージしてください
UartSendBuf[i] と書いた場合はUartSendBuf[i]に入っている数値(居住者)を意味します
&UartSendBuf[i]と書いた場合は住所を意味します
それぞれ意味合いはぜんぜん違います
(まずその違いを理解してください)
もう少しポインタを学習された方がよいのではないかと思います
再度同じようなこと書きますが
配列変数の場合配列の要素書かずに変数名書いた場合その配列の先頭アドレスが渡されます
それが dequeue(UartSendBuf); と dequeue(&UartSendBuf[0]); は同じというのを意味します
特定の配列要素のアドレスを渡したい場合は
(&UartSendBuf[j] のように)必ず & と 要素番号 を書く必要があります
UartSendBuf[j] と書くと UartSendBuf[j]に格納されている数値が渡されます
(関数側はそれをアドレスと思い込んで処理を行います)
回答頂きありがとうございます。
>i = 8;
>QueueState = dequeue(UartSendBuf[i]);
大変申し訳ありません。QueueState = dequeue(&UartSendBuf[i]);
&をつけ忘れていました。
訂正して頂きありがとうございました。
>改造とかかれてますが
>>x[0]=QBuf[Head];
>のことでしょうか? そのコードであれば
>*x=QBuf[Head];
>と書いているのと同じですので結果は変わりません
これはやはり同じ意味になるのですね。
この質問内で2重に質問してしまったのですが、一応自分の理解が正しいか判断したくてしてしまいました。
QueueState = dequeue(&UartSendBuf[8]);
この関数の引数で渡しているデータはアドレスの番号なのですね。
&UartSendBuf[8]これのアドレスが0xFFFF08だったならば、関数内の”*x”も”x[0]”も 0xFFFF08というアドレスだということになるんですね。x[1]=0xFFFF09,x[2]=0xFFFF0A
ということになって行くんですね。
なんとなくですが、メモリ番地というのを意識するようになってよりマイコンの内部の仕組みが漠然とわかるようになりました。C言語とかわからなくても(それじゃダメじゃん)マイコンなどのIOレジスタ設定などはまさに住所に行って手紙を出しに行くみたいな感覚ですね。
それぞれの作業にkoi1234さんがおっしゃっているような専門用語がすでについているようなので、追って勉強していきたいと思います。
No.4
- 回答日時:
> QueueState = dequeue(UartSendBuf[i]);
> というように&を付けずにこのプログラムを動かした場合
動かす以前に、 & UartSendBuf[i] と UartSendBuf[i] とでは型が違うのでコンパイルエラーになりそうですが
回答頂きありがとうございました。
良くプログラムを作成していて、プログラムの動作を確認するときにシミュレートを使って結果を追って行った時にポインタがどのような動きをするのか理解していなくて混乱させられます。
koi1234さんがおっしゃったように引数にポインタが宣言されているような関数
BYTE dequeue(BYTE *x) こんな関数です。
これで、
BYTE dequeue(test);
で使うか、
BYTE dequeue(&test);
というのは本当にちんぷんかんぷんだったので、説明をもらってはっと気がつかされました。この点に関して型の問題でコンパイルエラーがでるとかというのは聞いたことがありますが、いまだにちんぷんかんぷんです。
これから頑張ります。
No.3
- 回答日時:
補足しておきます
(&UartSendBuf[0]); この場合UartSendBuf[0]変数の格納アドレスが渡ります
関数側で*X=123; とすると UartSendBuf[0]に123が代入されます
(UartSendBuf[0]); この場合UartSendBuf[0]にセットされている数値がアドレスとして渡されます
関数側で*X=123; UartSendBuf[0]に入っていた数値をアドレスと思い
どこか見当違いのメモリに123が代入されます
その後の結果は最初に書いたとおり
No.2
- 回答日時:
>QueueState = dequeue(UartSendBuf);
>このように使う方がいらっしゃったのですが
上記のように書いた場合は
dequeue(&UartSendBuf[0]);
と書いているのと同じです (UartSendBuf[0]) ではありません
回答頂きありがとうございます。、
QueueState = dequeue(UartSendBuf);
dequeue(&UartSendBuf[0]);
この2つの意味が同じということなんですね。”UartSendBuf”でアドレス番号を指すのですね。
再度質問させて頂き申し訳ないのですが
BYTE dequeue(BYTE *x)関数をちょっと改造してみて、
BYTE dequeue(BYTE *x)
{
if(Head==Tail){
if(QueueState != QSTATE_FULL){
return QSTATE_EMPTY;
}
}
x[0]=QBuf[Head];
Head=(Head+1)%MAX_BUF_NUM;
return QSTATE_VALID;
}
もし、このようにプログラムした場合、
i = 8;
QueueState = dequeue(UartSendBuf[i]);
というようにしてこの関数を使ったとしても、以前の関数の動作と全く同じということになるということでしょうか?
No.1
- 回答日時:
プログラムをちゃんと見たわけではありませんが
>というように&を付けずにこのプログラムを動かした場合、どのような動きをプログラムはしてしまうのでしょうか?
ポインタ使用した処理を処理を間違えると
・一見動いているように見える(実際意図した結果は得られない)
・アプリが暴走して異常終了する
・他のアプリを異常終了する(させる)
・システムに影響してOS自体が落ちる
どれかになります(そのときのメモリ状態でどうなるか不定って事です)
回答いただきありがとうございます。
なんかポインタって今でもかなり自分の理解量に疑いを持っていて、想像がつかない時が結構あり、他人のプログラムをみてて結構戸惑うことが多々あります。
ちょっとこの関数に似たもので
BYTE dequeue(BYTE *x)
これをこのように、
BYTE UartSendBuf[8];
QueueState = dequeue(UartSendBuf);
このように使う方がいらっしゃったのですが、この場合もどのようにプログラムが動いていくのかよくわかりません。たぶんですが、UartsendBufの配列変数が、すべてその関数内の引数として登録されて、これも関数プログラムが動作完了すると、UartsendBuf配列にその関数で得たデータがその配列に自動的に入っているというように使っているようなのですが、
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
先頭アドレスとは何ですか?
-
C# 配列の変数宣言について。
-
CSVファイルのデータを2次元配...
-
2次元配列を戻り値とする関数?
-
C言語初心者 ポインタについて...
-
配列をEraseしてもメモリが開放...
-
市販のビンゴカードについて
-
なぜ配列は0から始まるのです...
-
複数の選択範囲の行番号を個別...
-
VB2010でのコントロール多次元...
-
VBで構造体の配列を関数に渡す...
-
Functionの戻り値を2次元配列...
-
配列を使わずに、変数名を動的...
-
LGノートPCグラムについて
-
ポインタの配列のコンマについて
-
if文の判定条件に配列
-
配列内の文字間を排他的論理和...
-
配列の参照渡しで型が一致しま...
-
テキストファイルから文字列を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
先頭アドレスとは何ですか?
-
C言語で特定列だけを抽出して配...
-
配列の参照渡しで型が一致しま...
-
VBで構造体の配列を関数に渡す...
-
C++ vectorに配列をプッシュしたい
-
【速いブラインドタッチ】手を...
-
unsigned char配列への入力の仕方
-
配列をEraseしてもメモリが開放...
-
【C言語】配列の中に配列を入れ...
-
ExcelVBAで質問です。離れた二...
-
4勤2休のシフト作成
-
Functionの戻り値を2次元配列...
-
Redimした動的配列はEraseする...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
おすすめ情報