• ベストアンサー

unsigned int型について

C言語初心者です。 unsigned int型に関する質問です。 --------------------------------- #include <stdio.h> int main(void) { unsigned int in1 = 10; unsigned int in2 = -10; unsigned char ch1 = 10; unsigned char ch2 = -10; printf("in1 = %d\n", i); printf("in2 = %d\n", i); printf("ch1 = %d\n", ch1); printf("ch2 = %d\n", ch2); return 0; } --------------------------------- 上記のプログラムを作成して実行すると、結果は以下の通りです。 [実行結果] in1 = 10; in2 = -10; ch1 = 10; ch2 = 246; 変数in2の値を表示した結果に関してですが、 unsigned int型にも関わらず負の値「-10」が表示されるのは 何故でしょうか?

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

  • ベストアンサー
  • chirubou
  • ベストアンサー率37% (189/502)
回答No.3

他の回答者さんの通りですが、補足したいと思います。 C の printf() 関数は、他の関数(正確には引数の個数が決まっている普通の関数)とはすこし勝手がちがいます。 どう違うかというと、printf() で format に続く引数の型がどうなっているかは、printf() が呼び出されて printf() が fomrat を調べて始めて分かります。ここで「分かる」と言いましたが、どういう型なのかは format に "%d" だと int 型の引数がある、と思い込んでいるだけなので、そうでない型が来ていても、そのまま何も考えずに表示しようとします。 gcc でコンパイルすると型が違った場合、コンパイル時にチェックして警告が出たりします(ただし -Wall などの警告オプションを付けた時)。 ですから、極端な話、 char *p; printf( "%d\n", p ); とやってもちゃんと動作しますが、出力された数値はとんでもない数字になります。つまりポインタを符号付き整数だと思い込んで出力しているのです。 ということで、質問者さんの場合では、printf() の format に "%u" としてして「ここの引数は符号無し整数だよ」と教える必要があります。

masy0312
質問者

お礼

非常にわかりやすいご回答ありがとうございました。 勉強になりました。

その他の回答 (5)

noname#52489
noname#52489
回答No.6

printfでformatに%dを指定して、符号ありの整数として出力しているから。 符号なし整数で表示する場合は%uです。 32bitの変数で-10は0xfffffff6です。 (意味が解からなければ補数とかで調べて下さい。) だからin2には0xfffffff6っていう数値が入ってます。 これを符号ありの整数として扱うと-10です。 符号無しの整数として扱えば4294967286です。 試しに unsigned int in2 = 4294967286; や、 unsigned int in2 = 0xfffffff6; に書き換えて試してみてください。 同じ結果が得られることでしょう。 unsignedと宣言している以上、-10を代入するなんてことは普通はやっちゃダメです。

masy0312
質問者

お礼

基本的な間違いですね。失礼しました。 今後は気をつけます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

#4です。訂正。 汎整数拡張では、負数の変換についても正式に定義されているんですね。 ということは、 >unsigned int in1 = 10; in1=10 >unsigned int in2 = -10; in2= -10 + ( UINT_MAX + 1 ) = -10 + (4294967295+1)=4294967286 >unsigned char ch1 = 10; ch1=10 >unsigned char ch2 = -10; ch2= -10 + ( UCHAR_MAX +1 )= -10 + ( 255 + 1 ) = 246 であって、 >printf("in1 = %d\n", i); unsigned intからintへの変換で、intで表現可能なので、10と表示 >printf("in2 = %d\n", i); unsigned intからintへの変換で、intで表現不可能なので、処理系定義 >printf("ch1 = %d\n", ch1); unsigned charを引数に渡すときにintに変換、intで表現可能なので、10のまま。 intで表示しようとするので、10と表示 >printf("ch2 = %d\n", ch2); unsigned charを引数に渡すときにintに変換、intで表現可能なので、246のまま。 intで表示しようとするので、246と表示 ということですね。 ということで、 >printf("in2 = %d\n", i); が間違い(処理系依存)ということですか。 #intが32bit,char が8bitで考えています。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.4

>変数in2の値を表示した結果に関してですが、 > unsigned int in2 = -10; unsignedに負の値を代入しているし、 > printf("in2 = %d\n", i); unsigned intの値を%dで表示しようとしている。 つまり間違ったプログラムだから。「-10」が表示されたのはたまたまに過ぎません。 ちなみに、この中で正しいのはch1だけのはず。

  • x415f484f
  • ベストアンサー率71% (57/80)
回答No.2

> unsigned int型にも関わらず負の値「-10」が表示されるのは > 何故でしょうか? "%d" は signed int として扱うからです。 "%u" とすれば unsigned int として扱われます。 コード printf("in1 = %u\n", in1); printf("in2 = %u\n", in2); printf("ch1 = %u\n", ch1); printf("ch2 = %u\n", ch2); 結果 in1 = 10 in2 = 4294967286 ch1 = 10 ch2 = 246 printf のフォーマットについて調べてみてはいかがでしょうか?

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

printfの変換指定子"%d"で符号なしから符号ありへ型が変換されたためでしょう 変数の型と表示の型を合わせるなら printf("in1 = %d\n", in1); printf("in2 = %u\n", in2); printf("ch1 = %hhd\n", ch1); printf("ch2 = %hhu\n", ch2); としましょう

関連するQ&A

  • char型+char型ってint型? if(char型==int型)?

    C言語の「汎整数拡張(インテグラルプロモーション)」というものに関するものだと思います。 char型とchar型を加えた結果は、char型でしょうか。それともint型でしょうか。 (下のプログラムの printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ という部分の結果は4なので、int型と考えるべきなのかな。) 私は、char型とint型の加算の結果はint型だと思っていましたが、 char型とchar型の加算の結果はやはりchar型だと思っていました。 (それが間違えているのでしょうか。) if(a[0]==i) /* char型とint型の比較(?) */ の部分では、左辺はchar型、右辺はint型ですが、このように型の違う変数を比較しても文法上構わないのでしょうか。 (私は、「比較は必ず型の同じもの同士でしかできない」と思っていました。) 左辺はchar型のように見えて、じつはint型ですか。 #include <stdio.h> int main(void) { char a[4]; int i=77; printf("sizeof(int)は%d\n", sizeof(int)); printf("sizeof(char)は%d\n", sizeof(char)); printf("sizeof('M')は%d\n", sizeof('M')); printf("sizeof(a[0])は%d\n", sizeof(a[0])); a[0]='M'; a[1]=7+6; a[2]=a[0]+a[1]; printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ printf("sizeof(+a[0])=%d\n", sizeof(+a[0])); if(a[0]==i) /* char型とint型の比較(?) */ puts("a[0]==i"); else puts("a[0]!=i"); return(0); } ちなみにワーニングもエラーもなんにもでません。

  • int型の変数値をバイト列としてコピー

    あるint型の変数に格納されている情報を、バイト列としてコピーする方法で困っています。 変数の入っている領域をそのままコピーしたいので、memcpyを使うかと思うですが、 コピーされた結果を見ると文字列の並びが逆転しているように見えます。 --サンプルコード抜粋 unsigned int i= 12345; unsigned char *c; c = (char *)malloc(sizeof(int)); printf("i_hex=%x\n",i); memcpy(c,(int *)&i,sizeof(int)); 出力結果 i_hex=3039 cの出力結果 3930000000 単純にmemcpyではダメなのでしょうか? 実行環境は、CentOS(32bit)+gccです。よろしくお願いします。

  • プログラムの間違っている箇所が分かりません

    文字列の置換プログラムを作りたいのですが、下記のプログラムでは正常に動きませんでした。 例えば、「call」の「ll」を「sell」と変換しようとするとエラーがでてしまいます。 プログラミング初心者なので、どこが間違っているのかよく分からないです。 以下、問題のあるプログラムを記述します。 #include <stdio.h> void change(char *in, char *bef, char *af){     char tmp[100];     int i = 0, j = 0;     int flg=0;         for(i = 0; *(af + i) != '\0'; i++){         tmp[i] = *(af + i);     }     tmp[i] = '\0';     for(j = 0; *(in + j) != '\0'; j++){     if(flg == 0 && *(bef + j) == '\0'){             flg = 1;     }         if(flg == 1){             tmp[i++] = *(in + j);             tmp[i] = '\0';         }     }     for(j = 0; j<=i; j++){         *(in + j) = tmp[j];     } } int check(char *in, char *bef){       int i=0;     int flg=0;     while(*(bef+i)!='\0'){             if(*(in+i)=='\0' || *(in+i)!=*(bef+i)){             flg=1;             break;         }         i++;     }     return flg; } int main(){     char in[100];     char bef_ch[20];     char af_ch[20];     int i=0;     printf("文字列を入力して下さい。\n");     gets(in);     printf("置換したい文字列を入力して下さい。\n");     gets(bef_ch);     printf("置換後の文字列を入力して下さい。\n");     gets(af_ch);     while(in[i]!='\0'){         if(check(&in[i], &bef_ch[0]) == 0){             change(&in[i], &bef_ch[0], &af_ch[0]);         }         i++;     }     printf("置換結果を示します。\n");     printf("%s\n",in);     return 0; }

  • C言語のコードについて

    C言語の問題なのですか、作成したのですが内容がわからないです。 コードをわかりやすく解説していただけると嬉しいです。 #include <stdio.h> void printBinary(unsigned char num) { int i ; /*①上位ビットから順に表示する*/ for(i = 7 ; i >= 0; i--) { /*②シフトとマスクを使用しています。*/ printf("%d", (num>>i) &0x01 ); } printf("\n"); } int main(void) { unsigned char num1 = 0xD2;/*11010010*/ unsigned char num2 = 0x5E;/*01011110*/ printf("0xD2 : "); printBinary(num1); printf("0x5E : "); printBinary(num2); return 0; }

  • int型とchar型について

    C言語初心者です。 よろしくお願いします。 ◎1----------------------- #include<stdio.h> int main(void) { int ss[4]="789"; printf("%c\n",ss[0]); return 0; } --------------------------- ◎2----------------------- #include<stdio.h> int main(void) { int *p; p="789"; printf("%c\n",*p); return 0; } --------------------------- ◎1、◎2の2つのプログラムについて疑問があります。 ◎1の「int ss[4]="789";」と◎2の「int *p;」のintの部分は今まで、何の疑問も抱かず、「char」として入力していました。 そこでchar型は1バイトの整数、int型は4バイトの整数ということで容量が違うだけで、intとしても大丈夫だろうと思ったのですが、 ◎1では、「'initializing' : 'char [4]' から 'int [4]' に変換することはできません。」とエラーが出て、◎2では「'char [4]' から 'int *' に変換することはできません。」とエラーが出ます。 intは文字列は扱えないということなのでしょうか? 以上intだと実行できない理由がわかりません。 初歩的なことですいませんが、教えていただけると嬉しいです。

  • 文字列をa→1b→2...z→26に変換する

    文字列を上記のように変換して表示するプログラムについて #include<stdio.h> int main() {    char ch[10];    printf("小文字のアルファベットの文字列を入力\n");    scanf("%s",&ch);    int i=0,j=97;    while(ch[i]!='\0'){      for(j; j<=97+26; j++){        if(ch[i]==j){          ch[i]=j-96;          printf("%d\n",ch[i]);        }      }    i++;    }    return 0; } 一文字の場合は問題ないのですが複数になるとうまくいきません 実行例 a 1 hello 8 となってしまいます。 改善をお願いします。

  • 次のプログラミングが上手くいきません

    このプログラムを実行するとセグメンテーション違反が出てきて上手くできません… #include<stdio.h> #include<stdlib.h> int search_letter( char *str, char letter); int main(void){ int cnt; char in[100]; char ch; printf("Input a string: "); gets(in); printf("Input a letter: "); scanf("%c", &ch); cnt = search_letter( in, ch); printf("The number of letter '%c' is %d\n", ch, cnt ); return 0; } int search_letter( char *str, char letter) { char *p; int n; n=0; p=str; while(p != NULL){ if(letter == *p) n++; p++; } return n; } 実行結果が以下のようにならなければいけないのですが… ./pz1-2 Input a string: Mousukkari akidesune Input a letter: o The number of letter 'o' is 1 *"./pz1-2"と"Mousukkari akidesune"はキーボードから入力した文字です。

  • ラベリング処理プログラム

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> int column, row; unsigned char val[4] = {0,0,0,0}; unsigned char tmp[255]; int pos_y[4] = {-1, 0, 1, 0}; int pos_x[4] = {0, 1, 0, -1}; int i, j, x, y, label, level, label1; int label_count = 1; unsigned char *in, *out; void labeling_main(); void labeling_search(); void labeling_main() { for(i = 0; i < y; i++){ for(j = 0; j < x; j++){ printf("aaa\n"); if(out[i * x + j] == 255){ printf("bbb\n"); fflush(stdout); out[i * x + j] = label_count; labeling_search(label_count, i, j); label_count++; } } } } void labeling_search(int label_count, int x, int y) { for(i = 0; i < 4; i++){ if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; labeling_search(label_count,(pos_y[i]+y),(pos_x[i]+x)); } } printf("ccc\n"); } int main(int argc, char *argv[]) { int result; int head, Magic; unsigned char *image, *in, *out, *res, *ros; FILE *fin, *fout; if(argc!=3){ printf("Usage : %s input output\n",argv[0]); exit(1); } fin = fopen(argv[1],"rb"); /* -------------------- ヘッダ取得ここから -------------------- */ fgets(tmp,255,fin); if(tmp[0]!='P') return 0; sscanf(tmp,"P%d",&Magic); if(Magic < 1 || Magic > 6) return 0; do fgets(tmp,255,fin); while(tmp[0]=='#'); sscanf(tmp,"%d %d",&x,&y); if(x < 1 || y < 1) return 0; fgets(tmp,255,fin); sscanf(tmp,"%d",&level); /* ヘッダの確認 */ printf("P%d\n",Magic); printf("%d %d\n",x,y); printf("%d\n",level); /* 画素の読み込み */ in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in,sizeof(unsigned char),x*y,fin); fout = fopen(argv[2],"wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); //2値画像 for (i = 0; i < y; i++) { for (j = 0; j < x; j++){ if(in[i * x + j] > 120){ out[i * x + j] = 0; }else if(in[i * x + j] <= 120){ out[i * x + j] = 255; } } } labeling_main(); printf("Max label number:%d\n",label_count); free(in); free(out); fclose(fin); fclose(fout); } コンパイルは通るのですが実行するとlabeling_mainの if文でセグメンテーションが出てしまいます。

  • ポインタにによる値の表現と文字列の表現について

    ◎1------------------------------ #include<stdio.h> int main(void) { char *pt="ABC"; printf("pt=%s\n",pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("pp=%s\n",pp); return 0; } -------------------------------------- ◎2---------------------------------- #include<stdio.h> int main(void) { char *pt="ABC"; printf("*pt=%s\n",*pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("*pp=%s\n",*pp); return 0; } ----------------------------------- ◎3--------------------------------------- #include<stdio.h> int main(void) { int ary[5]={111,222,333,444,-1}; int* pt=ary; while(1){ printf("%d ",*pt); ++pt; if(*pt==-1){ break; } } puts(""); return 0; } ----------------------------------------------- 以上3つのプログラムで、◎1はprintfで「*」が付いてなく、正常に実行出来ました。 ◎2はprintfで「*」が付いてなく、エラーは出ませんが、文字列が表示されませんでした。 ◎3は文字列ではなく値ですが、printfで「*」が付いていて正常に実行できます。 これは、値の場合は「*pt」とすることで、ptのアドレスに値を代入しているという事で、「printf("%d ",*pt);」で実行できたということですかね? 文字列の場合は、先頭のアドレスを渡すだけなので、「printf("pt=%s\n",pt);」のようにしてアドレスを参照しないとダメであるということですか? ◎2で「printf("*pt=%s\n",*pt);」としてしまうと、何が起きてしまうのかわかりません。 以上、教えていただけると嬉しいです。

  • 変数について(足し算・引き算)

    #include<stdio.h> main () { int i ; int j ; printf("第1の引数は?\n"); scanf("%d" , &i); printf("%d\n" , i); printf("第2の引数は?\n"); scanf("%d" , &j); printf("%d\n" , j); printf("和は、%d\n" , i+j); printf("差は、%d\n" , i-j); printf("積は、%d\n" , i*j); printf("商は、%d\n" , i/j); return; } これを実行すると(iを20 jを10)としたときに 和は、30 差は、10 積は、200 商は、2 と表示されます。 しかし、このようにプログラミングすると 足し算や、引き算の値が変になります。 #include<stdio.h> main () { int i ; int j ; int tashizann = i + j; int hikizann = i - j; int kakezann = i * j; int warizann = i / j; printf("第1の引数は?\n"); scanf("%d" , &i); printf("%d\n" , i); printf("第2の引数は?\n"); scanf("%d" , &j); printf("%d\n" , j); printf("和は、%d\n" , tashizann); printf("差は、%d\n" , hikizann); printf("積は、%d\n" , kakezann); printf("商は、%d\n" , warizann); return; } これを実行すると(iを20 jを10)としたときに 和は、257 差は、-255 積は、256 商は、0 と表示されます。 変数で足し算や引き算を設定したものを引数として 使うと、値がおかしくなるのかを教えて頂けませんか。

専門家に質問してみよう