dポイントプレゼントキャンペーン実施中!

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になるのでしょうか?

文章がうまくまとめられていないのですが、どちらになるのでしょうか?

A 回答 (8件)

「通常の算術型変換」の話ですね。


結論からいえば1になります。

通常の算術型変換は、多くの二項演算子のオペランドに対して行われます。
ですので、個々の部分式ごとに解決されます。
    • good
    • 0
この回答へのお礼

ありがとうございます。

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

お礼日時:2009/09/16 11:43

&huってなんだ・・・


%huですね

この回答への補足

みなさん回答ありがとうございます。
一番上の方の補足にみなさんへのお礼や補足を書きます。

まず、(汎)整数拡張ですが、int以下の整数型をintへ拡張するものだと理解しています。
そのため、今回の分かりにくい例ですが、整数拡張は行われた後のものだとして書いたつもりです。

次に、printf表示ですが、unsigned intの計算で式の結果がマイナスになった場合本来はラップアラウンドが生じているはずだと思います。
しかしprintfでは自動的に値を変えてしまうらしく…
ラップアラウンドが生じてる場合は%uで表示する必要があるとのことです。

補足日時:2009/09/16 10:35
    • good
    • 0

printf( )が変数の符号や型を解析して自動で表示するわけではないのでこれで値を確認するのはあまり意味がないです。


プログラマ側が型や符号を意識して使わないとだめでしょう。
unsigned shortは &hu で表示しないと意図しない値が表示されることがあります。
    • good
    • 0

なんか間違った方向に誘導されそうですね。



まず、今回は「汎整数拡張」ではなく、「通常の算術型変換」に関するものです。
「通常の算術型変換」について調べてみてください。

次に,評価結果が符号無しになるにもかかわらず、%dや%ldで変換したのでは、正しい結果が得られないのは当然です。
    • good
    • 0

>例えば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 );
}
    • good
    • 0

 これって整数拡張(汎整数拡張),汎整数昇格の話ですよね。

一度「整数拡張」でインターネット検索をおすすめします。既に参照済みであればご容赦願います。
    • good
    • 0

手元の環境で、試してみました。



#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}
*/
    • good
    • 0

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

この回答への補足

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

補足日時:2009/09/15 23:45
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!