### 質問
初歩的な質問なのですが、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/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
char
型は、システムによっては符号付きということがあります。そのため、「文字コードを表示したい」という目的で変換する場合、直接int
としてしまうとマイナスの値になり不都合なので、いったんunsigned char
に変換する、ということかと思います。
なお、printf
のような可変長引数の関数に、unsigned char
のようなint
未満の幅の値を渡すと、既定の実引数拡張という変換が入って、実際にはint
として渡されます。
投稿2020/02/09 22:19
総合スコア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総合スコア1382
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
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総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/10 02:20 編集
2020/02/10 02:09 編集
2020/02/10 02:19
2020/02/10 02:29 編集
2020/02/10 02:39
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
総合スコア7703
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/10 00:36
0
int型にキャストすればいいです。
それでなんか不具合はあるんでしょうか
投稿2020/02/09 22:04
総合スコア88042
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/10 01:55
2020/02/10 05:21
2020/02/10 05:24
2020/02/10 05:28
2020/02/10 05:31
2020/02/10 05:33
2020/02/10 05:41
2020/02/10 05:42
2020/02/10 05:45
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。