• ベストアンサー

算術型変換について

c言語で算術型変換がどのように行われているかの質問です。 例えばintが16bitでlongが32bitの環境であるとします。 そして以下のようなプログラムがあるとします。 unsigned long x = 100; signed int y = 1; unsigned int z = 5; long test = x + (y - z); 1、 このときまずy-zについて算術型変換が起きてyとzがunsigned intとなり、 y-z=65532となる。 そしてx/(y-z)について算術型変換が起き、xと(y-z)がunsigned longとり、 x+(y-z)=65632となるのでしょうか? 2、 もしくはx+(y-z)のすべてに算術型変換を起こしてから計算を行うのでしょうか? y-zの結果の型をunsigned longとして計算し、y-z=4294967292になるのでしょうか? 文章がうまくまとめられていないのですが、どちらになるのでしょうか?

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

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

「通常の算術型変換」の話ですね。 結論からいえば1になります。 通常の算術型変換は、多くの二項演算子のオペランドに対して行われます。 ですので、個々の部分式ごとに解決されます。

coco_75
質問者

お礼

ありがとうございます。 全体に算術型変換が行われるのではなく、部分式ごとに行われるのですね。

その他の回答 (7)

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

&huってなんだ・・・ %huですね

coco_75
質問者

補足

みなさん回答ありがとうございます。 一番上の方の補足にみなさんへのお礼や補足を書きます。 まず、(汎)整数拡張ですが、int以下の整数型をintへ拡張するものだと理解しています。 そのため、今回の分かりにくい例ですが、整数拡張は行われた後のものだとして書いたつもりです。 次に、printf表示ですが、unsigned intの計算で式の結果がマイナスになった場合本来はラップアラウンドが生じているはずだと思います。 しかしprintfでは自動的に値を変えてしまうらしく… ラップアラウンドが生じてる場合は%uで表示する必要があるとのことです。

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

printf( )が変数の符号や型を解析して自動で表示するわけではないのでこれで値を確認するのはあまり意味がないです。 プログラマ側が型や符号を意識して使わないとだめでしょう。 unsigned shortは &hu で表示しないと意図しない値が表示されることがあります。

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

なんか間違った方向に誘導されそうですね。 まず、今回は「汎整数拡張」ではなく、「通常の算術型変換」に関するものです。 「通常の算術型変換」について調べてみてください。 次に,評価結果が符号無しになるにもかかわらず、%dや%ldで変換したのでは、正しい結果が得られないのは当然です。

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.5

>例えばintが16bitでlongが32bitの環境であるとします。  「LSI C-86 Ver 3.30c 試食版」をRAMディスクに解凍し、実行してみました。 >文章がうまくまとめられていないのですが、どちらになるのでしょうか?  LSI C-86 では、1にも2にもなりませんでした。  ・まず( y - z )について、( 1 - ( 5 ) )で、-4。  ・次に、test = 100 + ( -4 ) で、96。  となったようで、「型変換が行われた」ことを確認できませんでした。 また、y と z の型を入れ替えても、同様でした(★、( y - z )で先に現れる y を、unsigned int に)。  これらから、( y - z )全体として(デフォルトの)、signed int となっているのかな?と思います。  というか、今回の例では、「整数拡張」をみるのに相応しくない「値」だったんではないでしょうか。 実行結果 x:100 size:4 y: 1 size:2 z: 5 size:2 ( y - z ):-4 0000FFFC size:2 test:96 ☆No.2 さんと異なるのは、sizeof( ( y - z ) )だけでした。 #include <stdio.h> void main() { unsigned long x = 100; unsigned int y = 1; /* ★ */ signed int z = 5; /* ★ */ long test; test = x + ( y - z ); printf( "x:%ld size:%d\n", x, sizeof( unsigned long ) ); printf( "y: %d size:%d\n", y, sizeof( unsigned int ) ); printf( "z: %d size:%d\n", z, sizeof( signed int ) ); printf( "( y - z ):%d %08X size:%d\n", ( y - z ), ( y - z ), sizeof( ( y - z ) ) ); printf( "test:%ld\n", test ); }

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

 これって整数拡張(汎整数拡張),汎整数昇格の話ですよね。一度「整数拡張」でインターネット検索をおすすめします。既に参照済みであればご容赦願います。

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.2

手元の環境で、試してみました。 #include <stdio.h> typedef unsigned long T_UINT32; typedef signed long T_SINT32; typedef unsigned short T_UINT16; typedef signed short T_SINT16; void run_test() {   T_UINT32 x = 100;   T_SINT16 y = 1;   T_UINT16 z = 5;   T_SINT32 test = x + (y - z);      printf("----------\n");   printf("x{%d} sizeof{%d}\n", x, sizeof(x));   printf("y{%d} sizeof{%d}\n", y, sizeof(y));   printf("z{%d} sizeof{%d}\n", z, sizeof(z));   printf("test{%d} sizeof{%d}\n", test, sizeof(test));   printf("----------\n");   printf("(y - z){%d} sizeof{%d}\n", (y - z), sizeof(y - z)); } int main(int argc, char *argv[]) {   run_test();      return 0; } /* 実行結果(gcc (GCC) 3.4.2 (mingw-special)): ---------- x{100} sizeof{4} y{1} sizeof{2} z{5} sizeof{2} test{96} sizeof{4} ---------- (y - z){-4} sizeof{4} 実行結果(Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86): ---------- x{100} sizeof{4} y{1} sizeof{2} z{5} sizeof{2} test{96} sizeof{4} ---------- (y - z){-4} sizeof{4} */

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.1

お手持ちのコンパイラで実験した結果は、どうなりましたか?

coco_75
質問者

補足

回答ありがとうございます。 手持ちのコンパイラではintもlongも32ビットであるため確かめることができておりません。 どちらかというと概念的に気になったので質問しました。

関連するQ&A

  • 汎整数拡張の通常の算術型変換

    「汎整数拡張」の「通常の算術型変換」に <一方のオペランドが型unsigned long intをもつ場合、他方のオペランドをunsigned long intに型変換する。> この下に「そうでない場合」が、一方のオペランドが型long intをもつ場合が二つ続きます。 <一方のオペランドが型unsigned intをもつ場合、他方のオペランドをunsigned intに型変換する。> <>2つの例はlong型やint型よりもunsigned型の上位に位置づけています。 例として   if(-1<1u)は偽になります。 何ゆえにunsigned型の上位性をしているのでしょうか。宜しく願います。

  • 暗黙的型変換

    C の文法書を読んでいると、 汎整数型拡張: int より小さな汎整数型が式中に現れる場合は、暗黙的に int 型に変換される。 算術変換: 二項演算子で二つのオペランドの型が違う場合は、演算前により大きな方の型に暗黙的に変換される。 とあります。 例えば int 型 = unsigned short 型 - unsigned char 型; はどのように暗黙的な型変換が行われるのでしょう。 int 型 = (int)unsigned short 型 - (int)unsigned char 型; でしょうか。あるいは、 int 型 = (int) ( unsigned short 型 - (unsigned short)unsigned char 型); でしょうか。

  • C言語signed long long型の演算

    C言語で以下の演算を行った場合、変数bに格納される値が-1(0xFFFFFFFFFFFFFFFF)になることを期待しておりましたが、参照すると4294967295(0x00000000FFFFFFFF)となってしまいます。 unsigned int a = 1; signed long long b; b = a * (-1); 32bit、64bitのUNIX(Solaris)マシンでそれぞれ確認しましたが、どちらも同じ結果となりました。 変数aの型宣言をsigned intにすると変数bが-1(0xFFFFFFFFFFFFFFFF)になることは確認したのですが、unsigned intだとなぜこのような演算結果となるのかが分かりません。 ※8バイト整数に格納する際に先頭4バイトがなぜ0xFFFFFFFFで補完されないのか? ちなみに変数bの型宣言をsigned long intにすると32bitマシンでは-1となりましたが、64bitマシンでは4294967295となってしまいます。 これは32bitUNIXマシンではsigned long intは4バイト領域であるため-1(0xFFFFFFFF)となり、64bitUNIXマシンでは8バイト領域のため前述と同じ結果になるのだと考えますが、なぜ8バイト整数を使用するとこのような演算が行われるのかが分からないので、演算順序や型変換の優先順位がどのように行われいるのか説明できる方教えてください。

  • 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) }

  • unsigned int型と int型の型変換の上位性

    if(-10<1u)の条件判定はunsigned型で評価され偽となります。 int型 unsigned int型とも32ビットで考えたとき、 1u = 0x00000001 -10 = 0xfffffff6で10進法では4294967286になります。 条件判定をunsigned型で考えれば確かに-10<1uは偽になり int型で考えれば-10<1uは真になります。 「通常の算術変換」によれば、「一方のオペランドがunsigned int型をもつ時、他のオペランドをunsigned int型に型変換するとあります。」 よって、if(-10<1u)の条件判定はunsigned型で評価され偽となりますが、 「一方のオペランドがint型をもつ時、他のオペランドをint型に型変換する。」では何故いけないのでしょうか? 宜しく願います。

  • シフト演算の結果の型

    シフト演算の結果の型は、左オペランドの型ということを聞きました。 この左オペランドの型というのは算術型変換をしてからのか、する前の型なのかどちらなのでしょうか? 例えば int a = -2; unsigned int b = 1; a >> b このときの結果の型は何になるのでしょうか? 算術型変換が起きる前のintになるのか? それとも算術型変換が起きるた後のunsigned intになるのか? 例文としてはおかしい点もあるかもしれませんが よろしくお願いします。

  • 2進数から10進数へ変換

    C言語で、2進数から10進数に変換するプログラムを作ろうと思っています。 手計算で行う場合は2進数の 下1桁目×1 下2桁目×2 下3桁目×4。。。と計算しています。 下○桁目を取り出す方法を考えているのですが、思いつきません。 3桁の2進数を変換するプログラム(とりあえず101を変換することを考えて・・・)を書いてみたのですが、101を考えすぎたためか上手くいきませんでした。 最終的には10進数でintの範囲内程度の2進数の変換ができるプログラムを書きたいと思っています。 アドバイスをお願いします。 ちなみに、考えてみたプログラムは以下の通りです。 101以外で上手く変換できませんね・・・ ここに貼り付けるのが恥ずかしいです。 #include <stdio.h> main() { int x ,i ,z[3]; scanf("%d",&x); z[0]=x/100*4; z[1]=(x/10-10)*2; z[2]=(x-110)*1; printf("%d",z[0]+z[1]+z[2]); return 0; }

  • char→10進数

    PICのプラグラムをC言語で書いています。 unsigned charでxを宣言して、xには電圧をAD変換した値(8bit)が代入されます。このxの値を10進数に変換したいのですが、char型をどうすればint型に変換すればいいのか分かりません。 自分なりに作ってみましたが、うまく動作しません。ご教授よろしくお願いします。 /*抜粋*/ unsigned char x; int y,i; float n; ・・・ y=0; for(i=7;i>=0;i--){   n=(((x>>i)<<7)>>7);   if(n==1)n=pow(2,i);   y=y+(int)n; }

  • バイナリの文字列を変換したい...

    Jpeg のExifを解析するスクリプトを書いてます あるバイナリの文字列を下記の形式に 変換する手段をどなたかご存知ないですか? (そもその下記の意味さえわからないですが) unsigned byte ascii strings unsigned short unsigned long unsigned rational signed byte signed short signed long signed rational single float double float よろしくお願い致します

    • 締切済み
    • PHP
  • xorshift

    xorshiftという乱数生成プログラムがあります。 この乱数の最大値が知りたいのですが、ご存じの方がいらっしゃいましたら教えてください。 unsigned long xorshiftrand(void) { static unsigned long x=123456789, y=362436069, z=521288629, w=88675123; unsigned long t; t = x ^ (x << 11); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); }

専門家に質問してみよう