質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

キャスト

キャストとは、オブジェクトの型の変換が許可された場合に、明白に別の型への変換を行うプロセスのことです。

Q&A

解決済

5回答

10152閲覧

c言語 char型からint型への変換

kelt22

総合スコア46

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

キャスト

キャストとは、オブジェクトの型の変換が許可された場合に、明白に別の型への変換を行うプロセスのことです。

2グッド

2クリップ

投稿2020/02/09 16:30

### 質問
初歩的な質問なのですが、char型からint型にキャストする場合は、なぜint型にキャストするのではなく、unsigned char型にキャストする必要があるのですが?またunsigned char型にキャストした値は、なぜint型になっているのでしょうか?

該当のソースコード

c

1#include<stdio.h> 2int main(void){ 3 char *str="abc"; 4 printf("%d",(unsigned char)*str); 5 return 0; 6}

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

kazuyakazuya, rubato6809👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

char型は、システムによっては符号付きということがあります。そのため、「文字コードを表示したい」という目的で変換する場合、直接intとしてしまうとマイナスの値になり不都合なので、いったんunsigned charに変換する、ということかと思います。

なお、printfのような可変長引数の関数に、unsigned charのようなint未満の幅の値を渡すと、既定の実引数拡張という変換が入って、実際にはintとして渡されます。

投稿2020/02/09 22:19

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

unsigned char型にキャストした値は、なぜint型になっているのでしょうか

まずこちらから。汎整数拡張が行われるからです。

汎整数拡張という裏方の仕組みがあることは、C言語の学習で案外見落とされるような気がします。これが結構重要な概念だということを示す良い質問です。
signed char, unsigned char は8ビットの値です。それが汎整数拡張されて32bitもしくは64bitの値として printf() 関数に渡されます。32bitか64bitかはコンパイラに依存します。私はintが16ビットという経験もあります。

int型にキャストするのではなく、unsigned char型にキャストする必要があるのですが?

提示されたコードはキャストしてもしなくても結果は同じですが、違う場合もあります。それは char の8bitの、最上位ビット(MSB)が1である場合、値としては0x80〜0xffである場合です。たとえば文字列に、いわゆる半角カタカナが含まれているとか。

最上位ビットが立っている値は符号付きでは負の値です。タダの char は signed char である場合が多いから、そのままだと 0x80は -128 = 0xffffff80 に汎整数拡張される可能性が高い。
しかし、これを 128 = 0x00000080 と拡張したい・表示したいから予め unsigned char と見做す=キャストしておく、コードを書いた人にそういう意図があったということです。

投稿2020/02/10 02:37

編集2020/02/10 02:40
rubato6809

総合スコア1382

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kelt22

2020/02/12 14:53

詳しい説明ありがとうございます。
guest

0

unsigned char型にキャストした値は、なぜint型になっているのでしょうか?

以下を参考に。
整数変換のルールを理解する

「追記」

asm

1main: # @main 2 .cfi_startproc 3# %bb.0: 4 pushq %rbp 5 .cfi_def_cfa_offset 16 6 .cfi_offset %rbp, -16 7 movq %rsp, %rbp 8 .cfi_def_cfa_register %rbp 9 subq $32, %rsp 10 movabsq $.L.str.1, %rdi 11 movabsq $.L.str, %rax 12 movl $0, -4(%rbp) 13 movq %rax, -16(%rbp) 14 movq -16(%rbp), %rax 15 movzbl (%rax), %esi # byteをintに変換 16 movb $0, %al 17 callq printf 18 xorl %esi, %esi 19 movl %eax, -20(%rbp) # 4-byte Spill 20 movl %esi, %eax 21 addq $32, %rsp 22 popq %rbp 23 retq 24.Lfunc_end0: 25 .size main, .Lfunc_end0-main 26 .cfi_endproc 27 # -- End function 28 .type .L.str,@object # @.str 29 .section .rodata.str1.1,"aMS",@progbits,1 30.L.str: 31 .asciz "abc" 32 .size .L.str, 4 33 34 .type .L.str.1,@object # @.str.1 35.L.str.1: 36 .asciz "%d\n" 37 .size .L.str.1, 4 38

投稿2020/02/10 01:41

編集2020/02/10 02:17
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/02/10 02:20 編集

今回はunsigned charを生成してそのままprintfの引数に渡している(演算はしない)ので、<del>これとはまた別件ですね。</del><ins>今回の説明には適当ではないかもしれません。</ins>
cateye

2020/02/10 02:09 編集

Cの場合は、整数変換規則(整数拡張)によってintになると思っていますが?
maisumakun

2020/02/10 02:19

提示されたページには、「プロトタイプ宣言にない引数を渡した場合に整数変換が適用される」ことが書かれていない、という意味合いです(変換自体は間違いないです)。
cateye

2020/02/10 02:29 編集

了解です。 ・・・むかし、pritf()の“intに満たない整数引数はintに拡張される”というのを確認した覚えが有るのですが・・・見つけられませんでした(_ _;)
guest

0

なんだか日本語のレベルで大混乱しているように見えますが...
そのプログラムの範囲では、キャストしようがしまいが実行結果に変化は見られないのが普通です(よほど特殊な文字コードを使っていない限り)。意図はプログラムの作者に聞いて下さい、としかいいようがないです。

そのプログラムにこだわらないなら、データを16進数表記でダンプしたい、なんて時にはそのようなプログラムを組みます。

C

1#include <stdio.h> 2 3int main(void){ 4 char str[]="こんにちは"; 5 char *p=str; 6 while(*p){ 7 printf("%02X ",(unsigned char)*p++); 8 } 9 printf("\n"); 10 char *p=str; 11 while(*p){ 12 printf("%02X ",(signed char)*p++); 13 } 14 return 0; 15}

あるいは、あるデータの部分8bitを取り出して表示したい、なんていうときには結構常套手段です。

C

1#include <stdio.h> 2 3int main(void){ 4 int a=-12345; 5 printf("%02X\n", (unsigned char)(a&0xff00>>8));//目的の8bitだけが表示される 6 printf("%02X\n", (signed char)(a&0xff00>>8));//余計な"FF"が表示される 7 return 0; 8}

いろいろ突っ込めば、特に指定のない'char型'がsignedかunsignedかは処理系依存(概ね「コンパイラによる」と解釈してもいいでしょう)だ、なんていうこともあります。これも、「多くの場合signed」でしょうけれど。


unsigned char型にキャストした値は、なぜint型になっているのでしょうか?

「unsigned char型にキャストした」かどうかは関係ありません。書式指定"%d"がint型を期待しているから、int型になります。

投稿2020/02/09 22:38

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/02/10 00:36

> 書式指定"%d"がint型を期待しているから、int型になります。 いえ、intとして認識されるのはprintfの問題でなくC言語レベルの実装です。%dにdoubleを渡すと正しく動作しません。
guest

0

int型にキャストすればいいです。
それでなんか不具合はあるんでしょうか

投稿2020/02/09 22:04

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2020/02/10 01:55

わざわざ unsigned にキャストしているということは、負の数を表示したくないということだと思います。
y_waiwai

2020/02/10 05:21

??どこかにそんな事書いてありました?
Zuishin

2020/02/10 05:24

その目的で割とよく使う書き方じゃないですか?
y_waiwai

2020/02/10 05:28

質問者がどういうつもりなのかが問題であって、アカの他人が決めつけるようなもんじゃないとは思いますが。
Zuishin

2020/02/10 05:31

この質問は unsigned char にキャストする意味を問うものです。最終的に int になりますが、キャストするかしないかでその結果が変わることがあります。 であるならば、とりあえず外してみて質問者の環境でたまたま不具合が出なければいいという主旨の回答では成り立たないと思います。
Zuishin

2020/02/10 05:33

質問者の「つもり」は「なぜこの書き方を(他人が)したのか」を聞きたかったのだと読み取れますが、どう読みましたか? 自分で書いたコードの意味を聞いているようには見えません。
y_waiwai

2020/02/10 05:41

まあ、回答者のスタイルの問題なんでしょうね。 こうであるはず、と決めつけて回答するのもいいんでしょうけど。
Zuishin

2020/02/10 05:42

意味を問う質問なので、意味を答えなければ質問に答えたことにはならないと思います。
Zuishin

2020/02/10 05:45

もちろん、キャストしてもしなくても全く同じ結果になるならこの回答でもいいとは思います。しかし明らかな違いがあるので。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問