久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5177|回復: 55
收起左側

表現奇怪的C語言0x80 正數?負數?bug?

  [復制鏈接]
ID:1043747 發表于 2022-9-12 08:46 | 顯示全部樓層 |閱讀模式
0x80在例子1表達式中為正數,在例子2表達式中為負數。
我不禁疑惑,0x80在表達式中什么時候被解釋為正數,何時是負數?

測試設備信息
開發板:普中A2
單片機:stc89c52rc
晶振:11.0592MHz
IDE:keil 5

單片機源程序如下:
  1. #include <STC89C5xRC.H>

  2. sbit led1 = P2^1;
  3. sbit led2 = P2^2;

  4. void main(void) {
  5.         
  6.         signed char a;
  7.         signed char byte, i, t;
  8.         // example 1
  9.         a = 0x80;
  10.         if (a != 0x80) led1 = 0; // led亮,說明if判斷中字面量0x80是正數
  11.         // example 2
  12.         byte = 0xa0;
  13.         i = 4;
  14.         t = byte & 0x80>>i;
  15.         if (t < 0) led2 = 0; // led亮,說明上一句中0x80被解釋為負數
  16.         while (1);
  17. }
復制代碼
1662943273743.jpg


表現奇怪的0x80.zip (17.09 KB, 下載次數: 19)
回復

使用道具 舉報

ID:94031 發表于 2022-9-12 10:07 | 顯示全部樓層
signed char 的范圍:-128-127 對于有符號數:最高位代表符號位: 0代表正數 1代表負數 。
回復

使用道具 舉報

ID:213173 發表于 2022-9-12 11:14 | 顯示全部樓層
signed char 聲明有符號型變量就得按C語言規定使用,數據范圍-128~+127。不是隨使用者意想而改變。覺得反復橫跳的是自己理解的問題?
回復

使用道具 舉報

ID:624769 發表于 2022-9-12 11:49 來自觸屏版 | 顯示全部樓層
正負數,是人為劃定的一個范圍,你要判斷正負,也是應該用if(a<0)來判斷,0x80在作為一個常量的時候,永遠是0x80,沒有正負數只說。之所以0x80賦值給signed char 聲明的變量后,變-128,是C語言,這么“認知”的。某種意義上其實就是“溢出”。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-12 12:16 來自觸屏版 | 顯示全部樓層
xuyaqi 發表于 2022-9-12 10:07
signed char 的范圍:-128-127 對于有符號數:最高位代表符號位: 0代表正數 1代表負數 。

我知道,但我說的是字面量0x80
回復

使用道具 舉報

ID:123289 發表于 2022-9-12 14:19 | 顯示全部樓層
本帖最后由 yzwzfyz 于 2022-9-13 08:34 編輯

完全看人為的定義!
必須事先規定!!
這樣才能沒有爭議。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-12 21:35 來自觸屏版 | 顯示全部樓層
188610329 發表于 2022-9-12 11:49
正負數,是人為劃定的一個范圍,你要判斷正負,也是應該用if(a

你說的對,0x80就是128,永遠是正數。
在例子2中,字面量0x80被解釋為負數,我認為是keil bug,你覺得呢?
回復

使用道具 舉報

ID:550613 發表于 2022-9-13 10:33 | 顯示全部樓層
你是從哪里得出0x80被解釋為負數的結論。
注釋的意思和你理解的意思真的一樣嗎?
這個注釋就一定是對的嗎?
回復

使用道具 舉報

ID:1043747 發表于 2022-9-13 12:03 來自觸屏版 | 顯示全部樓層
vca 發表于 2022-9-13 10:33
你是從哪里得出0x80被解釋為負數的結論。
注釋的意思和你理解的意思真的一樣嗎?
這個注釋就一定是對的嗎 ...

如果我哪里不對,你可以提出來啊,不要一味指責
回復

使用道具 舉報

ID:94031 發表于 2022-9-13 14:28 | 顯示全部樓層
censv 發表于 2022-9-12 12:16
我知道,但我說的是字面量0x80

字面量0x80 作為 signed char 應該是 -128
回復

使用道具 舉報

ID:624769 發表于 2022-9-13 17:51 | 顯示全部樓層
censv 發表于 2022-9-12 21:35
你說的對,0x80就是128,永遠是正數。
在例子2中,字面量0x80被解釋為負數,我認為是keil bug,你覺得呢 ...

t = byte & 0x80>>i;
從 這句, 以及你的結論看, 你完全沒有理解  變量和常量的關系, 以及 有符號數的運算規則。
你嘗試 把 上面這句, 分步寫出來。 然后嘗試,每一步 寫出注釋,說明這一步的目的,以及你認為得到的結果。看看,和你后面的 if 是不是能 銜接起來?

回復

使用道具 舉報

ID:1043747 發表于 2022-9-13 18:55 來自觸屏版 | 顯示全部樓層
188610329 發表于 2022-9-13 17:51
t = byte & 0x80>>i;
從 這句, 以及你的結論看, 你完全沒有理解  變量和常量的關系, 以及 有符號數的 ...

那我們再簡化一下,
當shift和result變量聲明為8位有符號類型
shift = 4;
result = 0x80 >> shift;
現在result是0xF8,如果字面量0x80被當做正數,左移4位后的結果是0x08。
結論:字面量0x80一定被當做了負數
回復

使用道具 舉報

ID:213173 發表于 2022-9-13 20:54 | 顯示全部樓層
censv 發表于 2022-9-12 21:35
你說的對,0x80就是128,永遠是正數。
在例子2中,字面量0x80被解釋為負數,我認為是keil bug,你覺得呢 ...

    signed char a;
    a = 0x80;
    if (a != 0x80) led1 = 0;//這里if只判斷真假,哪來的正負判斷?自己理解錯誤,不要懷疑keil bug,在keil里走單步看輸出窗口就一目了然了。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 06:15 來自觸屏版 | 顯示全部樓層
wulin 發表于 2022-9-13 20:54
signed char a;
    a = 0x80;
    if (a != 0x80) led1 = 0;//這里if只判斷真假,哪來的正負判斷 ...

if當然是判斷真假,a != x80,因為a表示為負數,不等于正數的字面量0x80,是對的。
但在第二個例子,0x80的左移,最高位補的是1啊,這就不正常了
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 06:18 來自觸屏版 | 顯示全部樓層
xuyaqi 發表于 2022-9-13 14:28
字面量0x80 作為 signed char 應該是 -128

0x80字面量應該是128,-0x80才是-128
回復

使用道具 舉報

ID:550613 發表于 2022-9-14 10:57 | 顯示全部樓層
censv 發表于 2022-9-13 12:03
如果我哪里不對,你可以提出來啊,不要一味指責

我沒有指責你的意思,我的意思是你要思考一下,你理解的意思和注釋的意思是不是一樣的,如果是一樣的,你是通過什么方法驗證的,是通過調試或者是其他方法驗證,最終得出這個結論的
回復

使用道具 舉報

ID:624769 發表于 2022-9-14 11:05 | 顯示全部樓層
censv 發表于 2022-9-13 18:55
那我們再簡化一下,
當shift和result變量聲明為8位有符號類型
shift = 4;

所以,我說你沒明白,什么叫 常量, 什么叫變量.   所以我讓你分步寫, 有助你理解.
result = 0x80 >> shift;  你為什么不分步寫?如果分步寫了,根本就沒有這樣的疑惑!
0x80 是 常量, 它能移位么??   不能! 所以, 你分步寫只能這樣寫:
result = 0x80;
result >>= shift;
看出來了么??  你的 result 是 有符號char  -128~127,  所以 0x80 賦值后,是-128, 明白了么??

提個小建議,你不如先 學 1禮拜 的匯編, 也不要深入, 了解一下 51的 運轉原理,以及常量變量的 應用關系,再回頭看這問題,就會發現根本不是問題。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 12:40 來自觸屏版 | 顯示全部樓層
本帖最后由 censv 于 2022-9-16 10:22 編輯
188610329 發表于 2022-9-14 11:05
所以,我說你沒明白,什么叫 常量, 什么叫變量.   所以我讓你分步寫, 有助你理解.
result = 0x80 >> shif ...
0x80是常量不假,但也是整數。
而且關于移位運算符兩個要求操作數都必須為整數,并且遵循整形提升原則,結果的類型是提升后的左操作數的類型。
所以對0x80的移位沒有任何問題。有問題的我仍然認為是keil的編譯沒有遵循c語言標準(沒有進行整形提升)

我還有些intel 8086的匯編知識,你能告訴我怎么查看keil編譯后的匯編代碼嗎
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 12:50 來自觸屏版 | 顯示全部樓層
188610329 發表于 2022-9-14 11:05
所以,我說你沒明白,什么叫 常量, 什么叫變量.   所以我讓你分步寫, 有助你理解.
result = 0x80 >> shif ...

不是不分步,是我不懂你的分布是什么意思?
我以為你是嫌代碼多懶得看,我只好把代碼再精簡一下
回復

使用道具 舉報

ID:624769 發表于 2022-9-14 13:20 | 顯示全部樓層
censv 發表于 2022-9-14 12:40
關鍵點來了,0x80是常量不假,但也是整數。
而且關于移位運算符兩個要求操作數都必須為整數,并且遵循整 ...

察看編譯后的 匯編代碼是  Ctrl + F5

我還是那句話, 常量是不能 做移位的,必須有個載體。
讓你做分步的目的,就是讓你 意識到這個 “載體”
你要分步的話, 肯定 不能  0x80 >>= result;  吧? 編譯絕對通不過。
由于你自己沒有分步, 所以,編譯器只好 幫你來分步。那么,怎么分?
你的受體目標是 result  編譯器 只好按 result 類型作為標裝, 來做0x80 的位移,理解了么?
如果,你正而8經的 分步寫:
ACC = 0x80;   
ACC >>= 4;
result = ACC;
自然,就不是你那個結果了。明白了么?
回復

使用道具 舉報

ID:526543 發表于 2022-9-14 13:28 | 顯示全部樓層

signed char 聲明有符號型變量就得按C語言規定使用,數據范圍-128~+127
回復

使用道具 舉報

ID:161164 發表于 2022-9-14 15:21 | 顯示全部樓層
試試if (a != (char)0x80) led1 = 0;
回復

使用道具 舉報

ID:879809 發表于 2022-9-14 15:35 | 顯示全部樓層
censv 發表于 2022-9-14 12:50
不是不分步,是我不懂你的分布是什么意思?
我以為你是嫌代碼多懶得看,我只好把代碼再精簡一下

你精簡的結果已經很明顯了,沒有人能看懂你在說什么東西。

你要把每一步都仔細寫出來,大家才能知道你哪里錯了。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 19:28 | 顯示全部樓層
發表于 2022-9-14 15:35
你精簡的結果已經很明顯了,沒有人能看懂你在說什么東西。

你要把每一步都仔細寫出來,大家才能知道你 ...

不知道你從哪認為的我認為自己絕對正確?

一上來就頤指氣使,你哪%出來的%!
你引用的那段也不是回復你的,和你有關嗎?
問不問的更不需要你指手畫腳

你既然看不懂,那說明你%,那就不要回復就好了。
如果你認為我態度不好,先看看你自己
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 19:52 | 顯示全部樓層
188610329 發表于 2022-9-14 13:20
察看編譯后的 匯編代碼是  Ctrl + F5

我還是那句話, 常量是不能 做移位的,必須有個載體。

非常感謝,通過看了反匯編我明白了。就是keil沒遵循c標準。

只是你說常量不能移位,我不認為是正確的,我上面中間回復的那句話是c語言標準上的。
移位運算并不要求左值(類似你說的「載體」),
0x80 >>= result; >>=不是移位運算符,這是賦值運算符,更準確的說是復合賦值運算符,賦值運算符要求左操作數是左值。0x80是常量是右值,不能作為左值使用。所以該語句非法。

result = 0x80 >> shift; 的執行順序,應該是0x80 >> shift 先運算,而非先看result的類型。因為移位優先級高于賦值
2022-09-14_190846.png

回復

使用道具 舉報

ID:624769 發表于 2022-9-14 20:18 | 顯示全部樓層
censv 發表于 2022-9-14 19:52
非常感謝,通過看了反匯編我明白了。就是keil沒遵循c標準。

只是你說常量不能移位,我不認為是正確的 ...

唉……,好吧,你覺得常量可以移位,就可以移位吧。
0x80 >> shift;   是不能獨立成語句的。
0x80 >>= shift; 是非法的。

result >> shift;  也是不能獨立成語句的。
result >>= shift; 是合法的。

移位必須在  A 寄存器操作。
任何變量,做移位操作,都會把 類型 帶入。
你是 singed char 就會 有 MOV C,ACC.7
你是 unsigned char 就會有 CLR C
如果你是 int 或者 Long  則還會有  XCH A,R7 這些操作。 選擇哪個操作,都是根據變量類型來定的。
但是,常量是沒有 類型的。 當然喜歡抬杠的會拿  22118400UL 這種來說事,我就不一一解釋了,就泛泛來講,我說的“載體” 就是 承載告知 編譯器 "類型" 的變量。
算了,你覺得怎么好理解就怎么理解吧,總之問題不在 0x80,也不是KEIL 的bug, 而是,在你的寫法。決定了最后的結果。
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 22:28 來自觸屏版 | 顯示全部樓層
本帖最后由 censv 于 2022-9-15 07:38 編輯
188610329 發表于 2022-9-14 20:18
唉……,好吧,你覺得常量可以移位,就可以移位吧。
0x80 >> shift;   是不能獨立成語句的。
0x80 >>=  ...

常量當然有類型,字面量常量0x80永遠是正的128。

咱們撇過以上分歧不談,你認為下一行語句執行后result變量的結果是多少,result聲明為signed char

result = 0x80 >> 4;
回復

使用道具 舉報

ID:1043747 發表于 2022-9-14 22:31 來自觸屏版 | 顯示全部樓層
188610329 發表于 2022-9-14 20:18
唉……,好吧,你覺得常量可以移位,就可以移位吧。
0x80 >> shift;   是不能獨立成語句的。
0x80 >>=  ...

0x80 >> shift;   是不能獨立成語句的。
result >> shift;  也是不能獨立成語句的。

這兩條都是合法的,編譯不會報錯
回復

使用道具 舉報

ID:879809 發表于 2022-9-14 23:04 | 顯示全部樓層
censv 發表于 2022-9-14 22:28
常量當然有類型,字面量常量0x80永遠是正的128。

咱們撇過以上分歧不談,你認為下一行語句執行后resul ...

c語言的魅力就在于貼近機器,0x80賦值給signed char后不是正數
回復

使用道具 舉報

ID:1043747 發表于 2022-9-15 07:16 來自觸屏版 | 顯示全部樓層
發表于 2022-9-14 23:04
c語言的魅力就在于貼近機器

0x80賦值給signed char并不影響原值,0x80也不會變成0x81
回復

使用道具 舉報

ID:624769 發表于 2022-9-15 10:52 | 顯示全部樓層
censv 發表于 2022-9-14 22:31
0x80 >> shift;   是不能獨立成語句的。
result >> shift;  也是不能獨立成語句的。

你確定, 這樣寫不會出 275 警告?
你 Ctril +F5 看過編譯結果么?
你知不知道, 這兩句, 壓根出不了 匯編代碼, 會被編譯器直接拋棄?

再回答上面你說的問題,
還是那句話, 常量是不能移位的, 所以:
result = 0x80 >> 4;   你看匯編代碼的話, 你只會 看到  MOV result,#08H  而完全看不到 移位的操作。明白了么?
C語言的優點,也是他的缺點, 當你不嚴謹的時候, 他會自己腦補。


回復

使用道具 舉報

ID:1043747 發表于 2022-9-15 16:57 來自觸屏版 | 顯示全部樓層
188610329 發表于 2022-9-15 10:52
你確定, 這樣寫不會出 275 警告?
你 Ctril +F5 看過編譯結果么?
你知不知道, 這兩句, 壓根出不了 匯編 ...

它們只是沒有產生副作用,出275警告恰恰說明它們是合法語句。至于不會產生實際機器碼,那是編譯器優化掉了。

通過result =0x80 >> 4;的對比就可發現,移位操作并不和result類型相關。根據你的分步而說,如相關result的結果只能是0xF8。至于看不到匯編代碼,那是因為0x80>>4是常量表達式,編譯時執行。

我發現使用反匯編來反推C語言,有些倒果為因了。
看匯編能解決為什么代碼在該平臺是這樣執行的,但解決不了編譯器為什么這樣翻譯,這還得回到C語言標準本身

有3點可以證明c語言常量移位是合法的
①編譯器不會報錯②c語言標準對移位運算符有明確描述,不存在類似a[ i]=i++;等關乎運算順序的歧義③vc,gcc,clang等編譯器對于result=0x80>>shift的執行結果都是0x08,而不是keil的0xF8。
回復

使用道具 舉報

ID:824490 發表于 2022-9-24 16:10 | 顯示全部樓層
一瓶農夫山泉,在超市里買2塊錢,同樣一瓶水,同樣的容量,當它在迪廳里,可是會被賣到20塊錢。
場景地點很關鍵!
所以,同樣的0x80,當它賦值給不同類型的變量時(signed char/unsigned char),其代表的含義什是不同的。
變量的類型一旦定義下來,在運行時是不會被改變的。
且繞開變量的類型去談它的正負值是沒有意義的。
回復

使用道具 舉報

ID:384109 發表于 2022-9-24 21:12 | 顯示全部樓層
怎么覺得討論的有點偏了,0x80的十進制是什么數,首先要定義0x80的數據類型,在編程里,十六進制數和二進制數不事先定義數據類型,數值就沒有意義,定義位有符號數,0x80-0xff就都是負數,定義為無符號數0x80-0xff就都是正數,至于0x80>>4,只是代表以0x80為具體數值進行移位操作,所以是可以實現也是正確的,但是移位結果同樣要看數據類型,無符號數移位是補零,有符號數移位是補1,不能因為移位而改變了數據的類型
回復

使用道具 舉報

ID:137736 發表于 2022-9-24 21:29 | 顯示全部樓層
看你定義,是有符合還是無符號。 signed char 與un signed char
回復

使用道具 舉報

ID:1043747 發表于 2022-9-26 15:50 來自觸屏版 | 顯示全部樓層
名字不是重點 發表于 2022-9-24 16:10
一瓶農夫山泉,在超市里買2塊錢,同樣一瓶水,同樣的容量,當它在迪廳里,可是會被賣到20塊錢。
場景地點 ...

你的意思是常量沒有類型,且談論她的類型沒有意義。對嗎?
回復

使用道具 舉報

ID:1043747 發表于 2022-9-26 15:52 來自觸屏版 | 顯示全部樓層
人中狼 發表于 2022-9-24 21:12
怎么覺得討論的有點偏了,0x80的十進制是什么數,首先要定義0x80的數據類型,在編程里,十六進制數和二進制 ...

那你認為0x80是什么類型?
回復

使用道具 舉報

ID:1043747 發表于 2022-9-26 15:54 來自觸屏版 | 顯示全部樓層
zmc419 發表于 2022-9-24 21:29
看你定義,是有符合還是無符號。 signed char 與un signed char

說的是常量0x80,不是變量,你可能沒認真讀
回復

使用道具 舉報

ID:384109 發表于 2022-9-26 16:08 | 顯示全部樓層
censv 發表于 2022-9-26 15:52
那你認為0x80是什么類型?

你這個問法就真的偏了,要先定義類型,再討論具體含義,而不是隨意討論,那樣沒結果的,這是很直接的因果關系,先因后果
回復

使用道具 舉報

ID:1043747 發表于 2022-9-26 18:00 來自觸屏版 | 顯示全部樓層
人中狼 發表于 2022-9-26 16:08
你這個問法就真的偏了,要先定義類型,再討論具體含義,而不是隨意討論,那樣沒結果的,這是很直接的因果 ...

那你的意思是常量沒有類型?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品亚洲一区二区三区在线观看 | 亚洲国产成人精品久久久国产成人一区 | 狠狠夜夜 | 国产一区二区三区高清 | 亚洲一区二区三区四区视频 | 久久精品亚洲精品国产欧美 | 婷婷中文在线 | 国产中文字幕av | 亚洲视频区 | 99爱在线 | 亚洲精品成人 | 欧美激情一区二区三区 | 国产 欧美 日韩 一区 | 99国产精品视频免费观看一公开 | 日韩视频a| 男女网站免费观看 | 免费一区二区三区 | 日日日操 | 久久精品视频免费观看 | 一区二区三区久久久 | 一级看片| 精品国产乱码久久久久久影片 | 国产 亚洲 网红 主播 | julia中文字幕久久一区二区 | 国产精品夜夜夜一区二区三区尤 | 九色 在线| 国产在线一区二区三区 | 9porny九色视频自拍 | 亚洲综合一区二区三区 | 一区二区亚洲 | 亚洲精品国产一区 | 亚洲日韩中文字幕一区 | 一级毛片色一级 | av电影一区二区 | 欧美在线观看一区 | 久久久久久国模大尺度人体 | 免费国产网站 | 在线视频一区二区三区 | 亚洲bt 欧美bt 日本bt | 久久99精品久久久 | 日韩av高清在线 |