型別轉換問題 |
|
syao
初階會員 發表:66 回覆:63 積分:25 註冊:2005-02-02 發送簡訊給我 |
#include <stdio.h>
#include int main() { if (-1L < 1U) printf ("True\n"); else printf ("False\n"); if (-1L > 1UL) printf("True\n"); else printf("False\n"); system("pause"); return 0; } Conversion rules are more complicated when unsigned operands are involved. The problem is that comparisons between signed and unsigned values are machine-dependent, because they depend on the sizes of the various integer types. For example, suppose that int is 16 bits and long is 32 bits. Then -1L < 1U, because 1U, which is an unsigned int, is promoted to a signed long. But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number 我測試好像結果跟書上不同 , 是否這就是書上說的根基器有關machine-dependent But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number 它是說-1L 會被提升到 unsigned long 而成的很大正整數 不過 -1L 不是是負數嗎??? 怎麼會提升到很大正整數 也搞不懂這樣提升如何讓-1L > 1UL ???? 還有-1L < 1U 也搞不太懂書上説的意思 懂得朋友可以跟我講一下書中的意思嘛??? 這本是 The C programming Language K&R 我相信應該滿多人看過的 可以把轉換提升後二進制的情況寫給我看嗎?? 就以書上意思 -1L > 1UL -1L < 1U 謝謝 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
|
syao
初階會員 發表:66 回覆:63 積分:25 註冊:2005-02-02 發送簡訊給我 |
===================引 用 文 章=================== suppose that int is 16 bits and long is 32 bits <<--這個假設在windows上就不成立了,因為都是 32bit 所以看不出來結果吧? to aftcast 我是想知道 書上的意思~~ 書上是假設以 int 2byte long 4byte But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number 它是說-1L 會被提升到 unsigned long 而成的很大正整數 不過 -1L 不是是負數嗎??? 怎麼會提升到很大正整數 我不懂的是-1L 是負數不是嗎???怎麼會提升到很大正整數這句話我搞不懂 那就算是提升到書上所謂很大的正整數那它怎麼如何比較它比 1UL 還要大??? 1UL 不是也算是 unsigned long 嗎?? 謝謝 |
justdo
高階會員 發表:2 回覆:359 積分:222 註冊:2004-08-17 發送簡訊給我 |
實際來看看-1L在記憶體中是怎麼表示的吧:
long i = -1L; unsigned char* p=(unsigned char*)&i; for (int i=0; i〈sizeof(long); i) cout << int(p[i]) << endl; 這段code在VC2005會跑出 255 255 255 255 也就是 -1L 在記憶體裡面是 0xffffffff 這個值改以 unsigned long 來看,就變成 4294967295 ,是unsigned long所能表示的最大值,所以比1大 重點在於怎麼去解釋一個值,當你用singed的角度去看的時候,會獲得-1 從unsigned的角度去看的時候,就會獲得最大值 ps: 自己把〈 換成 < ,找半天、試了半天,code還是無法正常顯示 XD |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
發現要send的時候,justdo已經回了,不過還是貼上來!
完全了解你想知道的東西了! 首先,要從資料儲存在媒體上的真實情形來看。其實 -1L 以電腦二進位來看,它是這樣子的(假設long是16bit以方便解說) 1111111111111111 (0xffff) 而正1UL當然就是 0000000000000001 (0x0001) 問題: 那麼請試想 unsigned long 的最大值是多大? 是的!也是 0xffff 也就是二進位 = 1111111111111111 我們可以發現其實一樣的資料對compiler來說有著不同的詮釋。這也是為何程式語言需要型別的關係。宣告型別就決定了資料以後的演算logic。 於是當compiler自動去type cast 的時候,它並沒有去改變實值的資料結構,只是改變了「詮釋」的logic。也就是 -1L 被改詮釋為 0xffffUL,這時候它當然比 1UL大了! 希望這樣的說明對你能有些幫助。 蕭沖 qs.xiao@gmail.com http://aftcast.blogspot.com/ --All ideals are worthless unless implemented--
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
syao
初階會員 發表:66 回覆:63 積分:25 註冊:2005-02-02 發送簡訊給我 |
===================引 用 文 章=================== 發現要send的時候,justdo已經回了,不過還是貼上來! 完全了解你想知道的東西了! 首先,要從資料儲存在媒體上的真實情形來看。其實 -1L 以電腦二進位來看,它是這樣子的(假設long是16bit以方便解說) 1111111111111111?? (0xffff) 而正1UL當然就是 0000000000000001???(0x0001) 問題: 那麼請試想 unsigned long 的最大值是多大? 是的!也是 0xffff 也就是二進位 = 1111111111111111 我們可以發現其實一樣的資料對compiler來說有著不同的詮釋。這也是為何程式語言需要型別的關係。宣告型別就決定了資料以後的演算logic。 於是當compiler自動去type cast 的時候,它並沒有去改變實值的資料結構,只是改變了「詮釋」的logic。也就是 -1L 被改詮釋為 0xffffUL,這時候它當然比 1UL大了! 希望這樣的說明對你能有些幫助。 蕭沖 qs.xiao@gmail.com http://aftcast.blogspot.com/ _________________________________________________________________________________________________ 你好: 改變了「詮釋」的logic 是指說沒去改變實際的值只是把存放長度擴大的意思嘛?? 就是16bit --> 32bit 去存放原來的值,但值還是不變 請問是這樣意思嘛? 謝謝 --All ideals are worthless unless implemented-- ? |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你說 : "改變了「詮釋」的logic 是指說沒去改變實際的值只是把存放長度擴大的意思嘛?? 就是16bit --> 32bit 去存放原來的值,但值還是不變"
是的! 可以那麼說。只是你用"值"這個字眼可能不夠精準。我覺得比較正確的說法是: 不改變實際的「資料結構」。為何這麼說? 在電腦的內部世界裡都是0101的二元概念。至於1111是什麼意思? 是數值? 是字元? 是多大? 這都是我們人類去定義的,以compiler的角度來說是型別來決定的。比如一樣的資料結構但賦予不同的型別宣告,則compiler會以不同的演算法(如比較大小)來處理。以你書上的二個例子來說: For example, suppose that int is 16 bits and long is 32 bits. Then -1L < 1U, because 1U, which is an unsigned int, is promoted to a signed long. But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number 例1: 當 int 是16位元,long 是32位元時,為何 -1L < 1U ? 答: 因為long的長度大於int,所以 1U會被轉成long的型別,而因為要被比的是 -1L(有號數),所以 1U正確的講會被轉成「有號的long型別」。若以memory的情形來看是這樣的: 原本1U的二進位結構是 : 0000000000000001 被轉型別時,一般來說結構都不會改變,但當後來的型別長度比原本長時會補0,1U --> 1L 00000000000000000000000000000001 此時 -1L < 1L (轉變後的情形,二個都是有號數的型別喔) 而第二個例子,昨天我有說明: -1L 與 1UL比較,此時二者長度一樣,只是型別不同。當compiler自動的把 -1L 轉成 unisigned long 時(其實用"轉成"的說法也是不精準,它事實上是"解釋成",因為資料結構沒變),-1L的資料結構被解釋成正4294967295而非 -1 。此時是二個無號數的比較。詳細再多看一下昨天post的文章。 我想你也必需要了解所謂"有號數"在0101裡是如何表達的。以 16 bit int 這個有號數來說,也就是如何表達-32,768 至 32,767 ? 用的是補數的方法(1變0,0變1,然後再加1),比如說 2 與 -2 的資料結構關係是: 正2 : 0000000000000010 負2: 1111111111111110 (先把正2的01互換,得到1111111111111101,然後再加1,得1111111111111110) 若要更了解,可參考一些Assembly組合語言的書。 可能的話請盡量的推敲我畫線的那句話的意義… 很求堪解的你很不錯喔 : ) 蕭沖 qs.xiao@gmail.com http://aftcast.blogspot.com/ --All ideals are worthless unless implemented--
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
syao
初階會員 發表:66 回覆:63 積分:25 註冊:2005-02-02 發送簡訊給我 |
to aftcast
謝謝你詳盡解說 關於你blog 中的以C語言觀點理解C 的this指標 #include #include #include typedef struct StudentInfo { char *mName; int mAgeInAc; int mAgeInTw; void (*mpCalc)(struct StudentInfo *self); int (*mpGetTwAge)(struct StudentInfo *slef); void (*mCopy)(struct StudentInfo *slef, struct StudentInfo src); }STI; /* 私人的方法 */ void ac_to_tw(STI *self) { self->mAgeInTw = self->mAgeInAc - 1911; } /*公開的方法*/ int get_tw_age(STI *self) { self->mpCalc(self); return self->mAgeInTw; } /*公開的方法*/ void copy(STI *self, STI src) { *self = src; } /*建構子*/ STI create_sti_object(void) { STI object; object.mName = 0; object.mpCalc = ac_to_tw; object.mpGetTwAge = get_tw_age; object.mCopy = copy; return object; } /*動態建構子*/ STI *p_create_sti_object(void) { STI *p_object = (STI *) calloc(1,sizeof(STI)); p_object->mName = 0; p_object->mpCalc = ac_to_tw; p_object->mpGetTwAge = get_tw_age; p_object->mCopy = copy; return p_object; } /*動態解構子*/ void destroy_sti_object(STI *self) { free(self); } #pragma argsused int main(int argc, char* argv[]) { int my_tw_age; STI student_info; STI *p_student_info; STI my_info; STI babe_info; STI copy_info; /*沒有建構式的建立法*/ student_info.mName = "蕭一世"; student_info.mAgeInAc = 1951; student_info.mpCalc = ac_to_tw; student_info.mpCalc(&student_info); printf("%s 民國%d年生\n",student_info.mName,student_info.mAgeInTw); /*使用動態建構方式,且直接呼叫私人方法*/ p_student_info = p_create_sti_object(); p_student_info->mName = "蕭二世"; p_student_info->mAgeInAc = 1961; p_student_info->mpCalc(p_student_info); printf("%s 民國%d年生\n",p_student_info->mName,p_student_info->mAgeInTw); destroy_sti_object(p_student_info); /*使用建構子,且呼叫公開方法取回值,Instance1 */ my_info = create_sti_object(); my_info.mName = "蕭沖"; my_info.mAgeInAc = 1971; my_tw_age = my_info.mpGetTwAge(&my_info); printf("%s 民國%d年生\n",my_info.mName,my_tw_age); /*使用建構子,且呼叫公開方法取回值,Instance2A */ babe_info = create_sti_object(); babe_info.mName = "寶貝"; babe_info.mAgeInAc = 1976; my_tw_age = babe_info.mpGetTwAge(&babe_info); printf("%s 民國%d年生\n",babe_info.mName,my_tw_age); /*使用拷備函式,Instance2B */ copy_info = create_sti_object(); copy_info.mCopy(& copy_info, babe_info); strcat(copy_info.mName, "拷備"); copy_info.mAgeInAc = copy_info.mAgeInAc 7; my_tw_age = copy_info.mpGetTwAge(& copy_info); printf("%s 民國%d年生\n",copy_info.mName,my_tw_age); system("pause"); return 0; } 我在gcc & dev-c 編譯可以跑出結果但之後好像會發生記憶體錯誤訊息 , 下面訊息是我在gcc 下編譯後執行結果出現程式記憶體區段錯誤 (core dumped) Cetus:~$ ./class 蕭一世 民國40年生 蕭二世 民國50年生 蕭沖 民國60年生 寶貝 民國65年生 程式記憶體區段錯誤 (core dumped) 謝謝 |
syao
初階會員 發表:66 回覆:63 積分:25 註冊:2005-02-02 發送簡訊給我 |
===================引 用 文 章=================== 實際來看看-1L在記憶體中是怎麼表示的吧:? ?long i = -1L; ?unsigned char* p=(unsigned char*)&i; ?for (int i=0; i〈sizeof(long); i) ??cout << int(p[i]) << endl; 這段code在VC2005會跑出 255 255 255 255 也就是 -1L 在記憶體裡面是 0xffffffff 這個值改以 unsigned long 來看,就變成 4294967295 ,是unsigned long所能表示的最大值,所以比1大 重點在於怎麼去解釋一個值,當你用singed的角度去看的時候,會獲得-1 從unsigned的角度去看的時候,就會獲得最大值 ps: 自己把〈 換成 <!--,找半天、試了半天,code還是無法正常顯示? XD<--> __________________________________________________________________________________________ long i = -1L; char* p=(char*)&i; int j; for (j = 0; j < sizeof(long); j) printf("%d\n",(int)(p[j])); ________________________________________________________________________ to justdo unsigned char *p指標 我改成 char *p 指標 -1 -1 -1 -1 並非 255 255 255 255 -1L 在記憶體裡面是 0xffffffff 還是我觀念上搞錯了 想請問一下這邊 char * 跟用 unsigned char * 指標抓取的資料有何不同??? 我改成char *這樣印出來是 1. p[i ] ; 用 unsigned char * 跟用 char * 指標都是一次抓取 8 bit? 2 . 是因為 -1 在 char 下看1111 1111 char 是 signed 所以看成 -1 而 unsigned char 下看 1111 1111 255 嗎?? 3. p 指向 long i ... 再用unsigned char * 或是 char * 抓取8bit 長度的值 ... 我不懂是同樣 char * 跟 unsigned char * 都是抓取 8bit 長度 那為什麼 unsigned char * 可以把值看成 255 .... 而 char * 看成 -1 .... 指標不是只是抓取長度~~ 還是在printf 或是 cout 時候會查看指標是 unsigned char * 還是 char * 在進行輸出?? 4 . 為何要在(int) 轉型在輸出 5. long i 可以用 float * 或是 double * 去指向 i 嗎??? 還是 整數型態必須只能由整數型指標去指向 ~~ 如果這樣指向 那在假設 float 佔 2byte 跟 double 4byte float * = (float *) & i; // 這樣也是對i 抓取16bit 長度值嗎??? 還是一樣的疑問這時候輸出值會是以 float 型態去計算後輸出嗎?? 謝謝 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
謝謝你提供了一個bug report! : -)
問題出現在: strcat(copy_info.mName, "拷備"); //這句話有問題,雖然bcb上run一切沒問題,但改至 vc6 一樣有你說的問題。 請修正此行為 copy_info.mName = "寶貝拷備"; 原因是我從頭至尾並未使用動態配置記憶體的方式來處理 copy_info.mName 欄裡的 char * 指標。而是以靜態的指定。在靜態的記憶空間裡一開始僅配"寶貝"四個byte,而後來試圖要在它的後面加入拷備這4個byte就可能會產生access violation的情形。本來是為了要演示確實有copy過來並以copy的值來變化的…
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
我想你還是沒有把我post給你的那段有畫線的部份仔細的徹底了解! 再重看思考幾次吧!
>>1. p[i ] ; 用 unsigned char * 跟用 char * 指標都是一次抓取 8 bit? YES >>2 . 是因為 -1 在 char 下看1111 1111??? char 是 signed 所以看成 -1?? 而 unsigned char? 下看 1111 1111? 255?? 嗎????? YES >>3.? p 指向? long i? ... 再用unsigned char * 或是 char * 抓取8bit 長度的值 ... 我不懂是同樣 char * 跟 unsigned char * 都是抓取 8bit 長度 那為什麼 unsigned? char * 可以把值看成 255? .... 而 char * 看成 -1 ....? 指標不是只是抓取長度~~ 還是在printf 或是 cout 時候會查看指標是? unsigned char * 還是 char * 在進行輸出?? YES >>4 . 為何要在(int) 轉型在輸出 因為若不轉成int 型別,那麼同樣的"結構" 1111 1111,又會被解釋成"字元",於是會印出字而非數值。 所有問題的關鍵都是 在電腦的內部世界裡都是0101的二元概念。至於1111是什麼意思? 是數值? 是字元? 是多大? 這都是我們人類去定義的,以compiler的角度來說是型別來決定的。比如一樣的資料結構但賦予不同的型別宣告,則compiler會以不同的演算法(如比較大小)來處理 1111 11111的結構對compiler來說可能是 字元,若你宣告它是 char,也可能是正數,也可能是負數當你宣告signed。 型別決定該資料的演算法,而演算法決定了大小的比較,print,各式各樣的function。for example: "1" "2" = "12"; 1 2 =3; 有什麼不同? 因為型別不同導至演算法不同!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |