1

私の理解をテストするために、この小さなコードを書きました。しかし、その背後にあるいくつかの事実を理解していませんでした。私は 64 ビットのリトル エンディアン マシンで作業しています。したがって、任意のポインターは 8 バイトです。つまり

#include<stdio.h>
int main(){
    char *c = (char *)0x12345678889;
    long a = 1;
    int b = (long)(c-a);
    /* int cc = (int)(c-a); gives compiler error */
    printf("val = %x and b = %x", c-a,b);
    return 0;
}
Output
val = 45678888 and b = 45678888

開始アドレスが 100 だとします。したがって、char*100->89、101->88 ... 105->12 としてメモリに格納され、バイト 106 と 107 は使用されません。そもそもこの私の推測は正しいのでしょうか?int と long は 64 ビット マシンでは 4 バイトであるため、100、101、102、および 103 から開始し、これらのバイトのみを考慮します。45678889 - 1 = 45678888.私の理解は正しいですか? 最後に、コメント行でコンパイラ エラーが発生している間はわかりません。コンパイラは、上記の行を暗黙的に型キャストしました。しかし、なぜ下にないのですか?

4

1 に答える 1

1

最初に、値がどのように格納されるかをアプリオリに知りませんでした。それはマシンのエンディアンに依存します。値は、最小桁から最大桁へ、またはその逆で保存できます。あなたのものは低から高までです。

次に、多くの 64 ビット マシンでは、int の長さは 4 バイト、長さは 8 バイトです。何が起こるかというと、あなたのマシンc-aはどちらが0x12345678888タイプであるかを計算し(char *)、それをlongwith 値に変換してから、0x12345678888静かに切り捨てます (C では long は黙って int に変換されます)。

コメントは警告を発します。これc-aは型char *であり、黙って に変換できないためですint(int にするのは非常に危険であると考えられています)。それでは、明示的に変換しましたが、コンパイラはそれも危険であると警告します。これらはエラーではなく警告であることに注意してください (コンパイラ オプションに依存する場合があります...)。

于 2013-09-11T16:35:19.640 に答える