亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7269|回復: 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. }
復制代碼



表現奇怪的0x80.zip (17.09 KB, 下載次數: 19)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

55#
ID:384109 發表于 2022-10-7 14:41 | 只看該作者
不管常量還是變量,都是先定義類型,再定義數值的,而且編程語言里還有隱性規則的,為什么正數128我們不用寫正號,就是因為隱性約定只有負數要寫符號,樓主一再強調0X80是什么數,確一直不能理解是需要先定義數據類型的,這個無法理解樓主為啥想不通,而且又看了樓主的例子,第一個例子if(a != 0x80),這是一個比較兩個數是否相同而已,又不在于是否有符號
回復

使用道具 舉報

54#
ID:526108 發表于 2022-10-7 08:35 | 只看該作者
常量都是以unsigned處理
常量<常量 == unsigned<unsigned

變量比較都是以變量作為單位
unsigned char<常量 == unsigned char<unsigned char
char<常量 == char<char

反匯編可以看這兩條c語言所編譯出來的匯編指令是不一樣的
回復

使用道具 舉報

53#
ID:526108 發表于 2022-10-7 08:23 | 只看該作者
188610329 發表于 2022-9-12 11:49
正負數,是人為劃定的一個范圍,你要判斷正負,也是應該用if(a

0x80是常量,常量都已unsigned處理
回復

使用道具 舉報

52#
ID:275826 發表于 2022-10-7 07:25 | 只看該作者
pdwdzz 發表于 2022-9-30 01:55
我送樓主個例子,相信樓主會更加堅信自己的見解,keil有bug,這么多年無人發現?
void main(void)
{

C51的關系運算==編譯成XRL,是有bug
回復

使用道具 舉報

51#
ID:275826 發表于 2022-10-7 07:22 | 只看該作者
0x80在沒有賦值給變量之前就是整形常量,是正數128
回復

使用道具 舉報

50#
ID:740383 發表于 2022-10-5 10:19 | 只看該作者
服,LED引腳初始化了嗎???輸入?輸出?準雙向?推挽?LED:0點亮還是1點亮???先不說定義,代碼本身就有問題
回復

使用道具 舉報

49#
ID:1043747 發表于 2022-9-30 16:46 來自觸屏版 | 只看該作者
我在此聲明一下,不要把0x80復制給變量,再來討論變量。這種討論和問題無關
回復

使用道具 舉報

48#
ID:740383 發表于 2022-9-30 10:22 | 只看該作者
xxxevery 發表于 2022-9-29 17:02
樓主不是偏了,是有探究精神,但還需要多多努力學習,我們大家都是這樣走過來的。對于0x80,我們回歸本質在 ...

無符號范圍char是0-255,,有符合范圍char是-128~+128,這里如果是數據,就是128,怎么規定它是浮點?它現在表示的是整數,換算十進制:128,想要定義為浮點float或者Double還需要加小數點:128.0,并且也不是你這樣描述的!盲猜樓主是想使用unsigned char與或運算,但是沒有&清零多余位.......
回復

使用道具 舉報

47#
ID:146878 發表于 2022-9-30 01:55 | 只看該作者
我送樓主個例子,相信樓主會更加堅信自己的見解,keil有bug,這么多年無人發現?
void main(void)
{
  signed char    a = 0x80;
  unsigned char b = 0x80;
  while(1)
  {
  if(a==b)
    LED0= 1; //如果進這里,那就是keil出bug了,啊哈哈哈哈哈。
  else
    LED0= 0;
  if(a>0)
    LED1= 1;
  else
    LED1= 0;
  if(b>0)
    LED2= 1;
  else
    LED2= 0;
    a++;
    b++;
  }
}
回復

使用道具 舉報

46#
ID:146878 發表于 2022-9-30 01:29 | 只看該作者
censv 發表于 2022-9-14 06:15
if當然是判斷真假,a != x80,因為a表示為負數,不等于正數的字面量0x80,是對的。
但在第二個例子,0x8 ...

這樣理解 != ,頭回見,頭回見。
。。。。。我沒說你理解的是錯的或怎么的,只是這理解方式,,頭回見。哈哈哈。
回復

使用道具 舉報

45#
ID:146878 發表于 2022-9-30 01:20 | 只看該作者
censv 發表于 2022-9-26 18:00
那你的意思是常量沒有類型?

常量可以有數據類型,但是你得表明是什么類型。不然編譯器不知道你要做什么類型。你不標明,那編譯器只能根據你的表達式去猜測你寫的常量是什么類型。
回復

使用道具 舉報

44#
ID:146878 發表于 2022-9-30 01:10 | 只看該作者
是keil沒按C標準,樓主按C標準了?
編譯器只要不明寫“該語句不是合法C語言”,那就是合法了。編譯不出來是編譯器的問題。
樓主說了寫常量0x80就應該是正數,大家記住,無論身處何地它就是正數,以后開發編譯器,別亂猜類型。

回復

使用道具 舉報

43#
ID:392485 發表于 2022-9-29 17:47 | 只看該作者
你把0x80放到 char型和int型中結果是不一樣的。定義成int型之后結果就不一樣了,因為第8位在char型中是個特殊位,在移位的時候會先看是做為正數處理還是作為符號位處理。keil是8位機的C語言。
回復

使用道具 舉報

42#
ID:59202 發表于 2022-9-29 17:02 | 只看該作者
樓主不是偏了,是有探究精神,但還需要多多努力學習,我們大家都是這樣走過來的。對于0x80,我們回歸本質在單片機中就是10000000,它可以是指令也可以是數據。而做為數據在編譯軟件的眼里它也是多種可能,你規定它是無符號數char它就是128,你規定它是有符號char它就是-128,甚至如果編譯軟件里有規定它還可以表示浮點數,這都不奇怪。我們學習c語言就要遵循它的規定,你違反了它的規定就會得到錯誤的結果這很正常
回復

使用道具 舉報

41#
ID:1043747 發表于 2022-9-29 13:51 | 只看該作者
人中狼 發表于 2022-9-26 18:58
不是常量沒有類型,而是類型不分常量或變量,否則有符號數怎么和負數常量做比較

我問 0x80 常量是什么類型,你說 這樣問是偏了,你的偏了是什么意思?
你又說,常量不是沒有類型,那你意思就是常量可能有類型。那常量什么情況下有類型?什么情況下沒有?
回復

使用道具 舉報

40#
ID:384109 發表于 2022-9-26 18:58 | 只看該作者
censv 發表于 2022-9-26 18:00
那你的意思是常量沒有類型?

不是常量沒有類型,而是類型不分常量或變量,否則有符號數怎么和負數常量做比較
回復

使用道具 舉報

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

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

使用道具 舉報

38#
ID:384109 發表于 2022-9-26 16:08 | 只看該作者
censv 發表于 2022-9-26 15:52
那你認為0x80是什么類型?

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

使用道具 舉報

37#
ID:1043747 發表于 2022-9-26 15:54 來自觸屏版 | 只看該作者
zmc419 發表于 2022-9-24 21:29
看你定義,是有符合還是無符號。 signed char 與un signed char

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

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

34#
ID:137736 發表于 2022-9-24 21:29 | 只看該作者
看你定義,是有符合還是無符號。 signed char 與un signed char
回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

31#
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。
回復

使用道具 舉報

30#
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語言的優點,也是他的缺點, 當你不嚴謹的時候, 他會自己腦補。


回復

使用道具 舉報

29#
ID:1043747 發表于 2022-9-15 07:16 來自觸屏版 | 只看該作者
發表于 2022-9-14 23:04
c語言的魅力就在于貼近機器

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

使用道具 舉報

28#
ID:879809 發表于 2022-9-14 23:04 | 只看該作者
censv 發表于 2022-9-14 22:28
常量當然有類型,字面量常量0x80永遠是正的128。

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

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

使用道具 舉報

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

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

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

使用道具 舉報

26#
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;
回復

使用道具 舉報

25#
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, 而是,在你的寫法。決定了最后的結果。
回復

使用道具 舉報

24#
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的類型。因為移位優先級高于賦值


回復

使用道具 舉報

23#
ID:1043747 發表于 2022-9-14 19:28 | 只看該作者
發表于 2022-9-14 15:35
你精簡的結果已經很明顯了,沒有人能看懂你在說什么東西。

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

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

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

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

使用道具 舉報

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

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

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

使用道具 舉報

21#
ID:161164 發表于 2022-9-14 15:21 | 只看該作者
試試if (a != (char)0x80) led1 = 0;
回復

使用道具 舉報

20#
ID:526543 發表于 2022-9-14 13:28 | 只看該作者

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

使用道具 舉報

19#
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;
自然,就不是你那個結果了。明白了么?
回復

使用道具 舉報

18#
ID:1043747 發表于 2022-9-14 12:50 來自觸屏版 | 只看該作者
188610329 發表于 2022-9-14 11:05
所以,我說你沒明白,什么叫 常量, 什么叫變量.   所以我讓你分步寫, 有助你理解.
result = 0x80 >> shif ...

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

使用道具 舉報

17#
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編譯后的匯編代碼嗎
回復

使用道具 舉報

16#
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的 運轉原理,以及常量變量的 應用關系,再回頭看這問題,就會發現根本不是問題。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表