文字コードの出力について

このQ&Aのポイント
  • 符号付char型の変数で文字コードを出力するC言語プログラムの問題点について
  • 問題の文字コード「N」の変換についての解決策
  • 符号無しchar型の変数を使用する理由について
回答を見る
  • ベストアンサー

■ 文字コードの出力について ■

符号付char型の変数「moji」に文字を代入し、その文字コードの上位4ビットと下位4ビットをそれぞれAND演算でビットを抽出し、算術右4シフトと算術左4シフトで処理して元の上位4ビットと下位4ビットを入れ替えて文字コードを出力するC言語プログラムです。 例えば、「A」の文字コード「41」を「14」で出力します。 問題は「N」です。 「N」の文字コードは「4E」です。これを「E4」に変えて出力したいのですが、「ffffffe4」となってしまいます。 解決策は、符号無しchar型の変数にすることが分かりました。 なぜ、符号無しchar型の変数にしないと正常に表示できないのでしょうか? コンパイラは「Borland C++ Compiler 5.5」です。 お答えできる方、よろしくお願いいたします。

  • Dr_DAC
  • お礼率99% (133/134)

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

その出力には何を使ってますか? printf("%x",moji); のようにしているのでは無いでしょうか? printfのような不定長引数(引数がいくつあるか決まってないもの)の場合、char,shortはintに自動的に型変換されます。その際、char,shortの符号も考慮されます。 同じ0xE4でも signed char型の場合、 0xE4=-28 なので → intの-28に型変換→0xFFFFFFE4 (intが32bitの場合) unsigned char型の場合、 0xE4=228 なので → intの228に型変換→0xE4 となります。 解決策は次のようなものがあります ・unsigned charを使う ・printf("%x",moji & 0xff) ; 等として、下8bitだけを残す。 & の計算時にmojiはintへ型変換されます。 ・計算をintで行う 入力はchar型の変数mojiだとして、途中経過や結果はintを使う。 例えば、結果を入れる変数を int kekka とでもして printf("%x",kekka) ; なら期待通りになるはず。

Dr_DAC
質問者

お礼

大変勉強になりました。 ありがとうございました。

その他の回答 (3)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

一箇所訂正 > 計算をintで行う このときも char→intの拡張が発生するので int moji_int = moji ; などとするのではなく int moji_int = (unsigned char)moji ; int moji_int = moji & 0xff ; 等として、8ビットだけ有効にするのがよいでしょう。

Dr_DAC
質問者

お礼

大変勉強になりました。 ありがとうございました。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

ご質問とともに、書かれたソース「も」見せてくだされば、 ソースのどこに問題がありそうでどう修正すればよさそうかが 一発でわかるかもしれないんですが…。 なんか二度手間。

Dr_DAC
質問者

お礼

ご指摘ありがとうございました。

Dr_DAC
質問者

補足

これは大変失礼しました。 こちらになります。 なお、「moji」変数を符号無しchar型にすると解決します。 #include <stdio.h> void main(void) { char moji = 'N'; char MASK_A = 0xF0; char MASK_B = 0x0F; moji = ((moji & MASK_A) >> 4) | ((moji & MASK_B) << 4); printf("文字コード:%x\n", moji); }

  • notnot
  • ベストアンサー率47% (4847/10260)
回答No.1

符号ありの整数は、最上位ビットを符号ビットとみなします。右シフトした場合、最上位ビットを保存したままシフトします。 符号なし整数の場合は、右シフトすると最上位ビットにはゼロが入ってきます。

Dr_DAC
質問者

お礼

ご回答ありがとうございます。 「N」の文字コード「4E」は、「0100 1110」であり、上位4ビットの最上位ビットは「0」なので、算術右4シフトしても「0」を保持しますし、下位4ビットでは算術左4シフトなので、最下位ビットは「0」が入るかと思います。 表示は「ffffffe4」ですが、「f」を除けばe4と入れ替えしていることが分かります。 問題は、それ以降の「f」になりますが、「ffffffe4」が32bitで表示しているところも気になります。

関連するQ&A

  • シフト演算子について・・・意味がわかりません(T_T)

    左シフト演算子<<は最上位ビットの上位を削除して最下位に0を追加、 右シフト演算子>>は最下位ビットが削除されて、最上位ビットに最上位ビットと同じ値が補充される、 論理右シフト>>>は最下位ビット削除され、最上位に0が補充される。 と、ここまではわかりました・・・ ある問題で int n = -1>> 31; でnはいくつになるか?というのがあったんですが、 解説の意味がわかりません。 回答はー1です。 「>>演算子によるシフトでは符号ビットが拡張される」 意味がわかりません・・・(@_@) 「>>>演算子であったなら、符号ビットがゼロになるのでN=1となる」 え・・・???!!! ふごーびっと??? シフト演算子ですから、 「-1の31こ右にビットをシフトする」 んだな・・・と思ったところ、 まったくどう考えてよいのかわからず、 回答を見たところ、余計わからなくなりました。 だれかたすけてください(T_T)

    • ベストアンサー
    • Java
  • ビットシフトについて

    12ビットのデータ(符号付き)を16ビットのデータに変換したいです。 自分なりに考えたのですが・・・ 最上位ビット(符号を表すビット)の位置が違うので左に4ビットシフト、 右に4ビットシフトします(どちらも算術シフトとします) 例  0000 1011 1101 0101 (12bit のデータ) →1011 1101 0101 0000 (左にシフト) →1111 1011 1101 0101 (右にシフト) こうするとたしかに16ビットのデータの最上位ビットには12ビットのデータの符号が 反映されるように思えるんですが、符号を除いた値そのものが変わってしまいますよね? どうしたらいいでしょうか 切羽詰まってて文章めちゃくちゃで分かりづらいかとは思いますが、解答よろしくお願いします。

  • 算術シフトしたら、あれ?

    16進数ので各4ビット(4桁)で2進数で算術シフトしますが、符号部はぬいて元の16進数に戻すのですか?でもそうすると元の数より大幅に減ってしまいますよね。例題の 例題・A4A6(16)を2ビット算術シフトする。 A4A6(16)=1010 0010 1010 0110 (2) ・左へ2ビットシフトする。 1000 1010 1001 1000(2)=A98(16) ・右へ2ビットシフトする。 1110 1000 1010 1001(2)=8A9(16) というように、符号部ぬかしたら増えるはずが減ったり、減るはずが増えたりと。なんか変ですよね。 ちなみに符号部すべて入れて考えたら、 左へ算術シフト 8A98(16) 右へ算術シフト E8A9(16) 増えるはずが減って、減るはずが増えるというあべこべになってしまいます。 超基本的ことなんですが、なぜか本に記載されていなかったので書きました。ご協力ください。

  • javaにおけるCSV出力時の文字コード改行コード

    JavaでCSVを出力する処理を作りました。 下記コードだとUnix環境で文字コードSJISで改行コードLFで出力されますが、 Windows環境でもUnix環境でも一律、文字コードSJISで改行コードCRLFで出力されるようにしたいです。 何かいい方法はありませんでしょうか。 なお、printlnで出力している行が多い為、 bw,Print("日付" + 変数A + \r\n); というふうに一行づつ変更するのは避けたいと思っております。 try{ PrintWriter bw = new PrintWriter(new BufferdWriter(new OutputStreamWriter(new FileOutputStream(/tmp/test.csv),"SJIS"))); bw.println("日付" + 変数A); bw.println("氏名" + 変数B); ・ ・ ・ }catch(Exception e){ // ログに出力 }

    • ベストアンサー
    • Java
  • サロゲートペアの文字コード→文字変換

    サロゲートペアの文字コード→文字変換 Windows上でRubyを使って文字コードの書かれたファイルを読み込んで文字を出力しようとしています。 サロゲートペアの文字コードを文字に変換するにはどうしたらいいでしょうか? たとえば上位サロゲートがa、下位サロゲートがbであるとき、JavaScriptでは次のようにすれば文字が得られるようです。 var s; s = String.fromCharCode(a,b); alert(s); (参考:http://codezine.jp/article/detail/1592) これをRubyでやろうとしていていろいろ調べてみたのですが、探し方が悪いのかわかりません。 どう書けばよいのか教えてください。 なお、WinsowsはXPです。ファイルに出力して正しく出力されているかどうかを確認しています。 よろしくお願いします。

    • ベストアンサー
    • Ruby
  • 算術シフトの方法

    1101(=-3)を算術シフトで1ビット右シフトしたときの結果についてご質問いたします。 この算術シフトを私が計算すると、1110 (=-2)となってしまいます。 しかし、本当は-3の1/2で、1111(=-1)と余りになるはずですよね? なぜ計算が正しくできないのか教えてください。 上記計算は、手持ちの本を参考に、以下のようにして行いました。 (1)1101の符号ビットを残して、右に1ビットシフト (2)空いたスペースに符号ビットを挿入し、1110を得る

  • C++言語で文字列を出力するにはどうしたら良いですか。

    C++言語で文字列を出力するにはどうしたら良いですか。 今、ポインタの勉強中ですが、ポインタの使い方がよく分からないです。 次のコードで ---------- one two three ---------- を出力したいのですが、nしか出力できません。 どうやらoneのnしか出力できません。 どのようなコードを書いたら解決できますでしょうか。 ------------------------------------------- #include<iostream> using namespace std; char name[3][10]={{"one"},{"two"},{"three"}}; char f(const char *name,int i){ return name[i]; } int main(){ cout << f(name[0],1) << endl; } -------------------------------------------

  • 基本情報のCASLIIの平成18年春の問13

    基本情報のCASLIIの平成18年春の問13の問題です。 32ビットの2進数(被乗数)と15ビットの符号なし二進数(乗数)の乗算を行うプログラムなのですが、解説を読んでもわからない点があったので質問させていただきます。 32ビットの被乗数の方は上位16ビットと下位16ビットにそれぞれGR1,GR0に分けて格納しています。 ここで、GR1,GR0をGR3ビットだけ論理左シフトします。そうすると、上位16ビットの左端からGR3ビットはみ出します。解説のここまでは理解できたのですが、次からの文章が理解できませんでした。 「シフト前の下位(16-GR3)ビットがシフト後の上位(16-GR3)ビットとして残る。したがって下位語の上位GR3ビットを(16-GR3)ビット,つまりGR4ビット論理右シフトして,上位語の下位GR3ビットに転送する必要がある。」 というものです。 シフト前の下位(16-GR3)ビットというのはどこのことを指しているのか不明ですし、シフト後の上位(16-GR3)ビットも同様です。 また、なぜGR4ビット論理右シフトするとなぜ上位語に反映されるのかもわかりません。右シフトすれば上位語も右シフトされて反映下位から上位へビットが転送されないと思うからです。 ちなみに、GR3+GR4=16という関係を持っています。 それと、解説の画像は添付しておきます。

  • 改行コードについて

    phpで開発をしています。 テキストファイルに文字列を出力する際に、改行コードを扱う以下のような場合について、 ①$str='ab\ncd'; ②$str="ab\ncd"; ①の変数の内容を出力すると\nがそのまま出力されます。 ②の変数の内容を出力すると改行されて出力されます。 質問ですが、この二つの違いについては、 ①のときは\nという文字として出力された。 ②のときは改行コードとして出力された。 (バイトコードで見ると、二つのコードは違っている?) という認識で良いのでしょうか。 ご教示いただけますと幸いです。

    • ベストアンサー
    • PHP
  • ビット幅とその出力について

    C言語を習い始めた者ですが、ビット幅とその出力についてわからないことが二つでてきました。以下のソースコードを見てください。 #include <stdio.h> int main(void) { char ss[] = "ABCDEF"; void *vpt; int idt; vpt = ss; idt = * (char *)vpt; printf("char:%x\n", idt); idt = *(int *)vpt; printf("char:%x\n", idt); return 0; } 出力結果は char:41 char:44434241 となります。 一つ目のわからないことは char:41 についてです。私はchar型のビット幅は8ビットで文字ABの16進数を出力すると予想していました。ところが結果は 文字A の16進数の41のみが出力されました。Aの二進数は 1010、 Bの二進数は1011で それぞれ4ビットずつ持っていて合わせて8ビットになるのでそう考えていました。よくわかりませんが結果から、文字一文字に対して8ビットつまり1バイトに相当するのでしょうか? 二つ目は char:44434241 についてです。一つ目の質問に書いた推測が正しければ1文字を1バイトと考えて16進数にすると Aは41 Bは42 Cは43 Dは44 になります。しかしポインタの先頭のアドレスはAになっているはずなのになぜか出力は char:41424344 ではなくchar:44434241になっています。順序が逆になっているのでしょうか? Cをはじめたばかりなので基本的なところがわかっていないかもしれませんが、説明に不足があればつけたしますのでどうかよろしくお願いします。 

専門家に質問してみよう