- ベストアンサー
C言語超初心者の質問:ltoa関数の意味がわからない
- C言語の勉強中の超初心者が、PICマイコンのAD変換のプログラムで使われているltoa関数の意味がわからないという質問です。
- 特に、「ltoa(*のアスタリスクの意味」「((WORD*)の意味(アスタリスクの意味)」「(&ADRESL))の意味」「,ANString);の意味」について、分かりやすく解説してほしいとのこと。
- ネットでの検索でも確かな解答が得られず困っているため、誰でもわかるように解説をしてほしいとの要望もあります。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
超初心者とのことですが、次の用語は理解できてますか? ・ポインタ、アドレス ・型とキャスト(型変換) ・関数と引数 ・文字列 &ADRESL ADRESLのアドレス。 ADRESLの型が書いてないのでわからないが、 その型へのポインタになる。 (WORD *) キャストで、「ADRESLの型へのポインタ」を「WORD型へのポインタ, WORD *型」に変換。 * 単項の*は、ポインタが示す実体を参照するもの。 ((WORD*)(&ADRESL)) が WORD へのポインタなので、そのポインタが示すアドレスにあるWORD型のデータを参照する。 全体での意味は itoa 関数に 第1引数: *((WORD *)(&ADRESL)) 第2引数: ANString を指定したもの。 itoaがどんな動作をする関数なのかは、マニュアルを読むこと。 おそらく、char ADRESL[] みたいになっていて、 ADRESL[0]とADRESL[1]の8bit+8bitを、16bitのデータ(WORD型)と見做して、atoiで処理する、ということではないかと予想します。
その他の回答 (2)
- kmee
- ベストアンサー率55% (1857/3366)
・WORD型 C言語では、typedefを使って、既存の型に別名を付けることができます。 また、マクロを使って、コンパイル前に置換することができます。 たしかに、WORDという型は、C標準にはありません。 なので、ヘッダ等のどこかでtypedefまたは#defineでWORDを定義しているはずです。 1ワードと言うと符号無し16bitを指すケースが多いです。 16bitのunsignedの整数がどの型になるかは、コンパイラや対象次第で決まりはありません。 なので、int型が16bitの環境ではunsigned int, shortが16bitの環境では unsigned short がWORDとして定義されていたりします。記述がバラバラなのはこのためです。 実際に何なのかは、#includeで取り込むヘッダファイルのどこかにtypedefや#defineでWORDが定義されているはずなので、確認してください。 ・ポインタの型 「そのアドレスに格納されたものの型ということでしょうか?」 はい、そうです。 ・二つに跨いで格納 よくある実装です。 場合によって、2つの8bitのレジスタとして別々に利用したり、つなげて1つの16bitのレジスタとして利用したりします 追加された情報からすると。 メモリ上では ADRESL ADRESH の順番に並んでいます。これはリトルエンディアンと呼ばれるものです。 &ADRESL は、ADRESLのアドレスですが、そのまま *で実体にアクセスすると、ADRESLの8bitしかアクセスできません。 そこで、このポインタをWORD *型に変換することで、ADRESH ADRESLを組み合わせた16bitのWORD 型へのポインタにします。 * でそのWORD型にアクセスするので、 16bit(実際には、そのうちの10bitにしかデータは入っていませんが)の値としてアクセスできるようになります。 その16bitの数値を、ltoaで文字列にします。元が611なら、ANStringは"611"です。 これは ANString[0] = '6' ; ANString[1] = '1' ; ANString[2] = '1' ; ANString[3] = '\0' ; になります。 この中で、PICマイコン独自なのは、「ADRESL, ADRESH レジスタの関係」だけです。 それ以外はPCでも使われるテクニックです。
お礼
またまた、早速のご回答ありがとうございます。 先ほどのお礼回答後に本を見て見ましたが、正しくご回答の通りと思います。 (今回のご回答も難しい言葉が出てきますが、何となくですがこの通りだとわかりました。) まだ、PICに関してもC言語も本を見て1週間くらいですので、確かに理解しておりませんでした。 ポインタに関しての型に関しても頭がパニックになりますが、ちゃんと記載がありました。 厚かましいようですが、応用が利く段階ではないのでできればご教示お願いします。 今やりたいことはADRESLの中身をスケール変換した後にltoa関数で文字列変換ができれば正しくANString配列変数へ文字が代入されると思います。 どのようにしたら、中身を(ADRESL * 50) /1024;の値にできるでしょうか? 自分なりに考えたんですが、配列変数の場合にはANString = (ANString * 50) /1024;のようにすると配列先頭の'6'かと思いましたが、(6*50)/1024=0.2929… となるので、中身ではなく、配列の先頭アドレスの値が計算対象になっているのではないでしょうか? 実際のVBソフトでの表示は5になっていますので、6ならば0.2929でも合わないし、611であれば29.83…となり、これは温度として正しい値となります。 したがって、どちらも5とはかけ離れているので色々考えてANStringはアドレスの値ではないか?と思った次第です。 間違っているでしょうけど・・・ もう一つ、最終的にANStringに代入された値(ご回答いただいた下記の内容)をスケール変換できないのでしょうか? ANString[0] = '6' ; ANString[1] = '1' ; ANString[2] = '1' ; ANString[3] = '\0' ; 最終的には (611*50)/1024=29.83 の29.8の値が、できるのかわかりませんが下記のようになればと思っております。 ANString[0] = '2' ; ANString[1] = '9' ; ANString[2] = '.' ; ANString[3] = '8' ; ANString[4] = '\0' ; 小数点は使えるのでしょうか? これも基本的なことなのでしょうが・・・ 文字列であれば問題無い? ど素人のたわごとにお付き合いいただきまして誠に恐縮ですが、ご教示をお願い申し上げます。 本来であればもう少し勉強してお伺いしなくてはならないことは、十分わかっております。 ありがとうございます。
- LHS07
- ベストアンサー率22% (510/2221)
*はポインターのことです。 基礎の基礎がまだ理解していないようですので、地平線から太陽が見え始めるようになりまで教科書をひたすら読みましょう。 今が一番辛いときですが読み続ければかならずわかってきます。楽しくなってきます。
お礼
早速のご回答ありがとうございます。 下記の件ですが・・・ ・ポインタ、アドレス ・・・ポインタは変数が格納されたアドレスを記憶する変数と理解しておりま す。 ・型とキャスト(型変換)・・・基本的な型は本を見ればわかりますが、PICの本には「WORD」という型は記載がありません。 キャストは変数の型の変換に使用すると理解しており、下記のようにポインタの型の変換ができるとは知りませんでした。ポインタの型ということは、「そのアドレスに格納されたものの型ということでしょうか?」 WORD型について調べましたが、intと書かれたり、unsigned short 型と書かれたり、まちまちなんですが実際にはどれが正解なんでしょうか? (WORD *) キャストで、「ADRESLの型へのポインタ」を「WORD型へのポインタ, WORD *型」に変換 ・関数と引数・・・関数と引数は何となくですが、ある程度理解できます。少なくとも下記については理解できます。 itoa関数とありますが質問ではltoa関数ですが、両方共同じような関数で、数値を文字列に変換する関数と理解していますが、itoaはint用でltoaはlong用と思っていますが、このように理解してよろしいでしょうか? 全体での意味は itoa 関数に 第1引数: *((WORD *)(&ADRESL)) 第2引数: ANString を指定したもの。 itoaがどんな動作をする関数なのかは、マニュアルを読むこと。 ・文字列・・・何となく理解できます。 最終的な解説内容についてですが、説明不足で申し訳ございません。 ある程度、詳しく説明しますとPICに関しても初心者なのでよく理解していませんが、PICマイコンで温度センサーのアナログ信号をAD変換した時のデータの格納先がPICで言う「ADRESLレジスタ」で変換結果のデータは10bitの電圧データとのことです。このデータをVBで作成したプログラムで温度として表示するというもので、実際の温度が611とかあり得ない温度の数値になっており、これを正常な温度数値とするためにスケール変換という作業が必要なのですが、最終的なPIC側の結果(ANString変数)にスケール変換用の式(ANString = (ANString * 50) /1024;)を書き込みコンパイルしましたが、これまた5とかあり得ない数値になってなっています。 わからないながら考えましたが、ASCIIに変換した後にスケール変換ができないのではないか? 文字列を計算することはできない? と思い、当質問文の前にスケール変換する式が必要になると考えました。 それには当質問文を理解しないとできないと思い質問させていただきました。 また、ADRESLの詳細としては(これもまた、理解に苦しんでしますが・・・) 実際の結果は ADRESH(8ビット) と ADRESL(8ビット)に10ビットで格納されるようです。 イメージとしては |ADRESH |ADRESL | 0000111111111111 となっていて、1111111111の部分が実際の格納データで、二つに跨いで格納しているようです。正直わけがわかりません。 本の内容は理解できませんが、当質問文の内容で最終的に「ANString配列変数」に本データがASCIIに変換されて代入されるようです。 正直、ネットで調べてもPICのC言語とは趣が違い、調べれば調べるほど理解に苦しみます。 もう少し、いろいろ調べて勉強します。 ありがとうございました。