• ベストアンサー

C90とC99の計算結果の違い?

C言語の質問です。 gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12) 以下のプログラムをgccでコンパイル・実行すると(1)に入り,"a"が出力されます。unsigned intの計算なのでラップアラウンドが生じtest=4294716272となるのは私の期待どおりです。 ただ、gcc -std=c99でコンパイル・実行すると(2)に入り,"b"が出力されました。c99でコンパイル・実行すると計算結果がなぜ異なっているのかが分かりません。 long test = 0; unsigned int x = 184; unsigned int y = 251208; test = (x-y); if(test == 4294716272){ printf("a");// (1) }else if(test == -251024){ printf("b"); // (2) }

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

C90では、longの表現範囲を超える10進整数定数はunsigned long型になります。 したがって、 if(test == 4294716272){ の部分は、testが通常の算術型変換によってunsigned longに変換され、符号無し整数として比較が行われます。 それに対して、C99では、longの表現範囲を超える10進整数定数はlong long型になります。 したがって、上記の箇所では、testはlong long型に変換され、符号付き整数として評価されます。

参考URL:
http://www.kijineko.co.jp/tech/creintro/size-of-int.html
coco_75
質問者

お礼

test == 4294716272 で算術型変換されるのを忘れてました。。。 納得いきました。 ありがとうございます。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

ついでに: gcc-4.4.3 では, gcc -o hoge hoge.c とこのまま C90 でコンパイルすると this decimal constant is unsigned only in ISO C90 と警告を出してくれます.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

C90 と C99 では, 「10進整定数の型」の決め方が異なります. いずれも「その値を表すことのできる最も小さな型」でますが, C90 では int → long → unsigned long の順に調べるのに対し C99 では int → long → long long の順に調べます. 今の場合 4294716272 は int でも long でも表現できないため, C90 では unsigned long として, C99 では long long として扱います. 従って C90 の環境では test を unsigned long に変換するので (1) に入りますが, C99 の環境では test を long long に変換するので (1) には入りません.

coco_75
質問者

お礼

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

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.2

> unsigned intの計算なのでラップアラウンドが生じtest=4294716272となるのは私の期待どおりです。 計算はunsigned intでもtestがlong型なので、longにキャストされて代入されているでしょう。 動作の違いは > if(test == 4294716272){ のlong型とunsigned int型の比較が、unsigned long型で行われるかlong long型で行われるかの違いでは?

coco_75
質問者

お礼

その通りですね。 ありがとうございました。

関連するQ&A

  • 計算が終わらないはずなのになぜか終わる?

    以下のプログラムをVisual stadio 6.0でコンパイルし プロジェクトの構成をWin32 releaseを選択し実行したら一瞬で計算が終わりました。約2^64の計算量であるので明らかに終わらないはずなのですがどうしてなんでしょうか? #include <stdlib.h> #include <stdio.h> void main() { unsigned int y; unsigned int x3; unsigned int out[16]={0}; for(y=0x1;y<=0xfffffffe;y=y+0x1){ for(x3=0x1;x3<=0xfffffffe;x3=x3+0x1){ x3 = x3 +1; y = y + 1; out[15] = y; } } //printf("%0x\n",out[15]); }

  • 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; } という結果になりました。 どうしてでしょうか? ご回答の程、宜しくお願い申し上げます。

  • 論理演算について

    Cを勉強中の者です。論理演算についてよくわからいことがあります。 以下のソースコードを実行し結果が真なら0001、偽なら0000が出力されるプログラムを作りました。 #include <stdio.h> int main(void) { unsigned short a = 0x1234; unsigned short b = 0xfafc; unsigned short c = 0xcdef; unsigned short x, y; x = a && b; y = b && c; printf("x=%04x\n", x); printf("y=%04x\n", y); return 0; } 結果はx=0001, y=0001となります。y=0001はbとcの文字列がそれぞれfとcをを持っているので演算による結果は納得できますが、x=0001はaとbの文字列には共通するものがないのになぜx=0000ではないのでしょうか? また0xが頭に付く表現は16進数だと強調するためにあるのですか? 説明に不足があればまた足しますのでよろしくお願いします。

  • printf()関数の括弧を二重にして、printf((~~~))とし

    printf()関数の括弧を二重にして、printf((~~~))として コンパイル/実行すると、実行時セグメンテーション違反が発生します。 コンパイル時には警告も発生しますが、このセグメンテーション違反が なぜ起こるのか理由がよくわかりません。ご回答いただけるとありがたいです。 以下、サンプルコードと実行例です。よろしくお願いいたします。 ---mytest.c---- 1 #include <stdio.h> 2 3 int main(void){ 4 5 //printf("test:%d", 1)ではもちろんコンパイル/実行に成功する。 6 printf(("test:%d", 1)); 7 return 0; 8 } 【コンパイル/実行結果/gccバージョン】 #gcc main.c main.c:6:警告:passing argument 1 of printf makes pointer from integer without a cast #./a.out セグメンテーション違反です # gcc --version gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27) ・ ・

  • C&C++、計算結果を表示する

    超初心者です。 本をみつつ勉強しているところなんですが、演習問題などやっていると、 コンパイルしてビルドして実行すると計算結果は目に見える形で出ずに終了・・するんですね。 それはprintf~がないから・・らしいということはココで聞いたりして微妙に判ったんですが、その記載の仕方を知りたいんです。 もしも『printf~~、と書けばどんな計算結果も表示される』というのがあるのなら、それを、そうじゃないのなら、その記述の仕方の決まりを教えてください。 計算の過程が見えないとできてるのかできてないのかわからなくて・・・。 よろしくお願いします。 一応、例を載せておきます。 main() { int a,b,i; a=b=i=0; while (i<100){ i++; if(i%2==0)a=a=i; else b =b+i; } }

  • C言語での計算

    C言語初心者で、計算するプログラムを作ってみようと思い、少ない知識で十進数を二進数にするプログラムを作ってみましたが、うまくいきません。 #include <stdio.h> #include <math.h> main () { int s, t, r; double x=10,y,n; printf("十進数は"); scanf("%d",&s); n = s / 2; r = s % 2; y = pow(x, n); t = y + r; printf("二進数は%d",t); return 0; } コンパイルして実行してみると、3つ問題が見つかりました。 (1)十進数が0のとき、二進数が1と表示される。 (2)十進数が1のとき、二進数が2と表示される。 (3)十進数が20以上のとき、正しい値が表示されない。 問題箇所を指摘していただけると幸いです。 よろしくお願いします。

  • C言語の演算について

    次のプログラムを実行したらどう出力されますか。 微妙な代入演算の違いが分からないので、教えていただけないでしょうか。 #include<stdio.h> void main (void) { int x = 5; int y = 8; int z = 3; int a,b,c,d,e,f; a = y == x + z; b = !x; c = x + y / z; d = x *=z - 1; e = --y / --z; f = y+++ % x++; printf("%d,%d,%d,%d,%d,%d\n",a,b,c,d,e,f); } できれば途中のトレースも書いていただけると助かります。 よろしくお願いします。

  • C言語に直して下さい

    VisualC++で円周率を求めるプログラムなのだそうですが、 自分はC言語しか使ったことがないため、よく分かりません。 Cでコンパイルできるように直していただけないでしょうか。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 21 #define K 100000 void add(unsigned long a[],unsigned long b[]) { int c = 0, tmp; for (int i = N - 1; i > -1; i--) { tmp = a[i] + b[i] + c; a[i] = tmp % K; c = tmp / K; } } void sub(unsigned long a[],unsigned long b[]) { int c = 0, x = 0; for (int i = N - 1; i > -1 ; i--) { x = c; if (a[i] < b[i] + x ) c = 1; else c = 0; a[i] = c * K + a[i] - b[i] - x; } } void div(unsigned long a[], unsigned long x) { int c=0, tmp; if (x >= K) { printf("Div Error\n"); getchar(); exit(1); return; } for (int i = 0; i < N ; i++) { tmp = (a[i] + c * K) / x; c = (a[i] + c * K) % x; a[i] = tmp; } } void clear(unsigned long a[]) { memset(a,0x00,sizeof(a)*N); } void set(unsigned long a[], unsigned long b[]) { memcpy(a,b,sizeof(a)*N); } void set(unsigned long a[], unsigned long b) { if (b<K) { clear(a); a[0]=b; } } int _tmain(int argc, _TCHAR* argv[]) { unsigned long pai[N], fn[N], gn[N], tmp1[N], tmp2[N]; int i; unsigned long n; clear(pai); clear(fn); clear(gn); clear(tmp1); clear(tmp2); set(fn, 16*5); set(gn, 4*239); for(n=0;n<40000;n++) { div(fn, 25); div(gn, 239); div(gn, 239); set(tmp1, fn); div(tmp1, 2*n+1); set(tmp2, gn); div(tmp2, 2*n+1); if (n%2==0) { add(pai, tmp1); sub(pai, tmp2); }else{ add(pai, tmp2); sub(pai, tmp1); } } for (i=0;i<N;i++) { printf("%5lu ", pai[i]); } getchar(); return 0; }

  • c言語のコンパイル後のエラ-について

    Unix,window98を使用しています。 #include<stdio.h> main() { doublea,b,x,y; a=1.0 ; b=2.0 ; x=a+1.0/b ; y=(a+1.0)/b ; printf(" a=%f\n b=%f\n x=%f\n y=%f\n",a,b,x,y); } を  gcc ファイル名.c    でコンパイルして、 % ./ファイル名      で実行すると、   ./ファイル名; コマンドがみつかりません。  と表示され、 % ./ファイル名.c     で実行すると、 ./ファイル名.c; アクセス権がありません と表示され、 % ./ファイル名.out    で実行すると、 ./ファイル名.out; コマンドが見つかりません。 となり、困っています。 お答えを頂ければ、嬉しいです。  

  • ファイル分割について

    今本をみながら練習中なのですが、ファイル分割がうまくいきません。以下のような3つのプログラムをかいたのですが実行できません。 (一つ目:myfunc.h) int max(int x,int y); (二つ目:myfunc.c) int max(int x,int y){ if(x > y) return x; else return y;} (三つ目:sample.c) #include <stdio.h> #include "myfunc.h" int main(void){ int x,y,c; printf("1番目の整数\n"); scanf("%d",&x); printf("2番目の整数\n"); scanf("%d",&y); c = max(x,y); printf("最大値は%d\n",c); return 0;} すべてコンパイルしてsample.cを実行してもだめでした。ご指導お願いします><