你的理解是正確的 - 數字應該改變。我拿走了你的代碼,並添加了一點點,以告訴你到底發生了什麼。
真正的問題是相當有趣的,並且與浮點數在內存中表示的方式有關。
首先,讓我們創建一個映射在你的結構中使用的字節數:
aaaa
bbbbbbbbxxxx
正如你所看到的,與a
前四個字節0重疊。這將變得重要。
現在我們來看看double
通常存儲的方式(我從Mac的角度寫這篇文章,內容是64位Intel架構,所以內存中的格式確實是IEEE754格式) :
這裏要注意的重要一點是,Intel的機器是「小尾」 - 也就是說,將首先被存儲的號碼是「在正確的事」,即最低顯著位的「分數」。
現在讓我們來看看一個程序,做同樣的事情,你的代碼一樣 - 但打印出結構的內容,所以我們看到正在發生的事情:
#include <stdio.h>
#include <string.h>
void dumpBytes(void *p, int n) {
int ii;
char hex[9];
for(ii = 0; ii < n; ii++) {
sprintf(hex, "%02x", (char)*((char*)p + ii));
printf("%s ", hex + strlen(hex)-2);
}
printf("\n");
}
int main(void) {
static union job
{
int a;
struct data
{
double b;
int x;
}q;
} w;
printf("intial value:\n");
dumpBytes(&w, sizeof(w));
w.q.b=7;
printf("setting w.q.b = 7:\n");
dumpBytes(&w, sizeof(w));
w.a=4;
printf("setting w.a = 4:\n");
dumpBytes(&w, sizeof(w));
w.q.x=5;
printf("setting w.q.x = 5:\n");
dumpBytes(&w, sizeof(w));
printf("values are now %d %d %.15lf\n",w.a,w.q.x,w.q.b);
w.q.b=7;
printf("setting w.q.b = 7:\n");
dumpBytes(&w, sizeof(w));
printf("values are now %d %d %.15lf\n",w.a,w.q.x,w.q.b);
return 0;
}
和輸出:
intial value:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
全零(我聲明變量static
- 確保一切都會被初始化)。請注意,該函數打印出16個字節,即使您可能認爲其最大元素爲double + int
的結構應該只有12個字節長。這與字節對齊有關 - 當最大元素長度爲8個字節時,結構將在8位邊界上對齊。
setting w.q.b = 7:
00 00 00 00 00 00 1c 40 00 00 00 00 00 00 00 00
讓我們來看看代表他們的正確順序double
字節:
40 1c 00 00 00 00 00 00
Sign bit = 0
exponent = 1 0000 0000 0111b (binary representation)
mantissa = 0
setting w.a = 4:
04 00 00 00 00 00 1c 40 00 00 00 00 00 00 00 00
當我們寫信a
,我們修改了第一個字節。這對應於尾數,這是的至少顯著位現在(在十六進制):
00 00 00 00 00 00 04
現在尾數的格式意味着1
到此號碼的左側;因此將0
中的最後一位更改爲4
,將數字的大小改變了很小的一部分 - 您需要查看十進制的十進制數來查看它。
setting w.q.x = 5:
04 00 00 00 00 00 1c 40 05 00 00 00 00 00 00 00
值5
在自己的小空間書面
values are now 4 5 7.000000000000004
注 - 當我用了大量的數字,你可以看到,b
最低顯著的部分是不完全7
- 即使double是完全能夠精確地表示整數的。
setting w.q.b = 7:
00 00 00 00 00 00 1c 40 05 00 00 00 00 00 00 00
values are now 0 5 7.000000000000000
再次寫入7
到雙後,你可以看到,第一個字節是再次00
,現在printf
語句的結果確實是7.0完全相同。
所以 - 你的理解是正確的。問題在於你的診斷 - 數量不同,但你看不到它。
通常,尋找這些東西的好方法就是將數字存儲在臨時變量中,然後查看其差異。那麼你會很容易找到它。
我相信OP的編輯非常清楚地表明問題是什麼(我正在改寫):「當我應該覆蓋結構中的數據時,數據如何變化」。我有一個答案准備好......我不能在問題關閉時發佈。 – Floris
@弗洛里斯現在開放。等待你的答案。 –
@JanDvorak謝謝 - 它現在在那裏。 – Floris