• ベストアンサー

型変換キャストについて

#include <stdio.h> int main( void ) { short a = 30000, b = 10000; long c; c = a + b; printf("%ld",c) return 0; } *ただし,short:2バイト,long:4バイト このプログラムをVisual C++でコンパイルすると 結果は40000とちゃんと表示されるのは何故ですか? shortは2バイトだからshort型のa + bの値は変な値になるはずで,本来次のようにキャストが必要だと思うのですが。 #include <stdio.h> int main( void ) { short a = 30000, b = 10000; long c; c =(long) a + b; printf("%ld",c) return 0; }

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

  • ベストアンサー
noname#5537
noname#5537
回答No.2

> このプログラムをVisual C++でコンパイルすると > 結果は40000とちゃんと表示されるのは何故ですか? C には算術変換というのがあります。 short 型同士の場合, 演算に先立って両オペランドが int 型に変換されます。 int 型が 4 バイトであれば,正しい結果が得られます。 short 型同士以外の場合の算術変換の規則については参考 URL を参照してください。 結構複雑です。

参考URL:
http://www.microsoft.com/japan/developer/library/vclang/_pluslang_arithmetic_conversions.htm
Rossana
質問者

お礼

回答ありがとうございます。 >int 型が 4 バイトであれば,正しい結果が得られます。 sizeof演算子を使って調べるとint型は4バイトとなっています。 なるほどそういうことなのですね。

Rossana
質問者

補足

yoppiiさんの言われたことを納得するため次のプログラムを比較しました。 #include <stdio.h> int main( void ) { int a = 2000000000, b = 1000000000; float c; c = a + b; printf("%f",c); return 0; } では結果が -1294967296.000000 となり変な結果になります。一方, #include <stdio.h> int main( void ) { int a = 2000000000, b = 1000000000; float c; c = (float) a + b; printf("%f",c); return 0; } では結果が 3000000000.000000 となり正しい結果が得られました。 これはint型同士の場合はfloat型への算術変換が行われていないからということですね!!

その他の回答 (2)

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

>c = a + b; >printf("%f",c); >return 0; >} >では結果が >-1294967296.000000 >となり変な結果になります。一方, 何故-1294967296.000000 になるか。 理由があります。 intが表せる範囲は-2147483648 ~ 2147483647です。(unsigned intだと0~4294967295です。) 2000000000 + 1000000000は2147483647をオーバーします。 2147483647を超えると値がマイナスになります(2147483647 + 1 → -2147483648) つまり 3000000000 - 4294967296 → -1294967296となりこの値(int)が暗黙にfloatにキャストされているのです。

Rossana
質問者

お礼

理由を解説していただきありがとうございました. ちょっとすぐに理解できなかったので, sha-girlさんの言われること(例えば,2147483647 + 1 → -2147483648)を理解するため,補数表示について勉強しました.この計算は分かったのですが,でも, 3000000000 - 4294967296 → -1294967296 がちょっとよく分かりませんでした. 補数表示では n桁のビット表現[a_(n-1),a_(n-2),…,a_1,a_0]_2 を-a_(n-1)2^(n-1)+Σ[k=0 to n-2]a_k2^kに対応させているというのは分かりましたが.

Rossana
質問者

補足

この式↓ 3000000000 - 4294967296 → -1294967296 の解説をお願いします.

  • ryuta_mo
  • ベストアンサー率30% (109/354)
回答No.1

ひとつの式に複数の型の変数がある場合自動で変換されます。 優先度は char short long float double  右のほうが優先度が高い です。 上の例ではコンパイラがlong型に自動で変換します。

Rossana
質問者

お礼

回答ありがとうございます。でも,この場合一つの式の中は同じ型shortですよね。だから,それが理由というのはなかなか素直に納得できないんですが。 ちなみに, #include <stdio.h> int main( void ) { short a = 3, b = 2; float c; c = a / b; printf("%f",c); return 0; } では結果が「1.000000」 #include <stdio.h> int main( void ) { short a = 3, b = 2; float c; c = (float) a / b; printf("%f",c); return 0; } では結果は「1.500000」となるのは納得できます。

関連するQ&A

  • GCCで暗黙の型変換の警告を出したい

    情報が失われてしまうような代入について警告を出したいのですが、 どういったオプションを用いればよいでしょうか? コンパイラはGCCの3.x系か4.x系でお願いします。 以下のようなソースで型変換に関する警告がほしいんです。 --- test.c --- #include <stdio.h> int main(void) {   int a = 66000;   short b;   b = a; // <- 暗黙の型変換   printf("%d\n", b);   return 0; } 実行結果 $ ./test 464 以下のオプションを試しましたが、上記のソースでは 何の警告も出ませんでした。 -W -Wall -Wconversion -Wimplicit ご存知の方いらっしゃいましたら、どうかお助け下さい。

  • 型変換の問題?

    次のプログラムなんですが #include <stdio.h> #include <math.h> #include <cstdlib> #include <iostream.h> void main(){ double v[10000]; for(int b=0;b<10000;b++){ v[b]=2.5+0.01*(double)(rand()%249+1);} for(b=0;b<10000;b++){ int c=(int)(100.*v[b])-251; if(c==192){printf("%d %f\n",c,v[b]);} }} 私の環境のVC++6.0 on win2kのもとで やってみると、printf("%d %f\n",c,v[b])のところで 192 4.43 となったり 192 4.42 となったりします。 真の値は、192 4.43のつもりでプログラムを組んだのですが、 なぜかc=(int)(100.*v[b])-251;という写像は 単射になっていないようです。 さて、質問ですが、double→int型の型変換に原因があるのでしょうか?

  • C言語の簡単な質問です。

    #include "stdio.h" int tasizan(int a,int b){ int c; c=a+b; return c; } int main(void){ int a,b,c; a=1; b=1; c=tasizan(a,b); printf("%d+%d=%d",a,b,c); return 0; } と、あるとします。この文を読み込む順番を教えてください。  文の左に行番号みたいに順番を書き込んでください。   例 (例が間違ってたらすみません) 1 #include "stdio.h" 2 int main(void){ 3 int a,b,c; 4 a=1; 5 b=2; 6 c=a+b; 7 printf("%d+%d=%d",a,b,c); 8 return 0; }

  •  現在、私はC言語を学んでいます。

     現在、私はC言語を学んでいます。  プログラミングの初期の初期の問題なんですが、 「Hello World」という有名なプログラムがありますよね? それについての質問です。 #include<stdio.h> main() { printf("Hello World"); return 0; } も #include<stdio.h> main(void) { printf("Hello World"); return 0; } も #include<stdio.h> int main() { printf("Hello World"); } もちゃんと表示できます。 ここで質問です。 int main(void) int main() main() main(void) はどう違うんですか? あと、 return 0; はあっても無くてもいいようなんですが どういう意味があるんでしょうか?

  • 型変換がうまく出来ない

     今晩は、Cの初心者です、宜しくお願いします。  下のようなコードを書きましたが、正常に表示されません。  一体何処が悪いのでしょう。 =========================================================== #include <stdio.h> #include <string.h> #include <ctype.h> int main(void) { char s2[20] = "0.789"; double ddt = atof(s2) ; printf("ddt = %lf\n\n" , ddt); printf("atof(s2) = %lf\n\n" , atof(s2)); printf("(float)idt + atof(s2)) = %lf\n\n" , ((float)idt + atof(s2))); return 0; }

  • C言語初心者です。

    C言語初心者です。 1^2-2^2+3^3-4^2…+99^2-100^2の値を求めるプログラムを作成したいのですが上手くいきません。 どこが足りないのですか? #include <stdio.h> int main(void) { printf("%d", 1^2 - 2^2 + 3^2 - 4^2 … + 99^2 - 100^2); return (0); } よろしくお願いします。

  • ASCIIコード入力

    プログラムを作っていてどうしてもわからなくなりまして… #include <stdio.h> int main(void) { char c; c=38; printf("%c\n",c); return 0; } この場合は&が出てくるからいいんですけど… #include <stdio.h> int main(void) { char c; scanf("%c",&c); printf("%c\n",c); return 0; } この場合は97をscanすると9が出てきます。ASCIIコード入力でaを表示させたいんですが、何が間違っているのでしょうか? 初心者なもので…お願いしますm(__)m

  • グローバル変数について

    ◎1--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; glb=30; printf("main a=%d glb=%d\n",a,glb); func(); return 0; } void func(void) { int b=88; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎1の実行結果----------------------- main a=20 glb=30 func b=88 glb=30 ------------------------------------- ◎2--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; func(); printf("main a=%d glb=%d\n",a,glb); return 0; } void func(void) { int b=88; int glb=30; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎2の実行結果----------------------- func b=88 glb=30 main a=20 glb=0 ------------------------------------- 以上2つのプログラムで、◎1は参考書を参考に作成したものです。 ◎1のプログラムで、グローバル変数glbの値をmain( )関数内で設定していたので、次に◎2のようにfunc( )という関数プロトタイプ内で、グローバル変数glbの値を設定し、main( )関数内のprintf文でも表示させようと思ったら、「glb=0」となってしまいました。 なぜこのようになってしまうか、教えてもらえたら嬉しいです。

  • C言語でO-Notepad-x,文字化け。

    いつも大変お世話になりありがとうございます。 標記の件。 ボクはTeraPadをエディターに使っています。 コードとコンパイル、実行がおかしくなりました。 コードと実行は下記の通りです。 #include <stdio.h> int main(void) { int a = 0; int b = 0; b = a++; printf("代入後にインクリメントしたのでbの値は%dです。\n", b); return 0; } C:\MinGW>gcc test1.c -o test1 C:\MinGW>test1.c 実行するとO-Notepad-xと言うのが起ち上がって #include <stdio.h> int main(void) { int a = 0; int b = 0; b = a++; printf(" ɃC N g ̂ b ̒l %d ł B\n", b); return 0; } という結果になりました。 どうしてでしょうか? ご回答の程、宜しくお願い申し上げます。

  • 2921を23で割ったあまりが0ならば画面に「yes改行文字」と書き、

     そうでなければ何もしないプログラムは、既に余りが0だということが分かっているんですが、 #include <stdio.h> int main(void) {int a, b,c; a=2921; b=23; c=a%b; if(c=0){ printf("yes\n"); }return 0;} で実行しても黒い画面は出るんですが、yesが出ません。何か問題ありますか?