[英]Why hardware register access is through unsigned datatype
我正在閱讀一些例子,並且在所有這些例子中都使用了unsigned。 如果使用正確,使用int類型是否安全? 與下面的示例類似,0x12345678地址將寫入0xFFFFFFFF,而不管ptr被定義為有符號還是無符號。
volatile unsigned int* ptr = (volatile unsigned int* ) 0x12345678;
*ptr = 0xFFFFFFFF;
為什么使用unsigned而不是signed來進行寄存器訪問是否安全?
我認為無符號C算法更接近機器寄存器算術。 這是因為C語言定義說,如果有符號整數算術運算結果為不符合給定類型(溢出)的數字,則操作的實際結果是未定義的。 所以它可以是任何東西。 在無符號算術中:
涉及無符號操作數的計算永遠不會溢出,因為無法用結果無符號整數類型表示的結果以比模式生成的無符號整數類型所表示的最大值大1的數量減少。
這與機器寄存器中發生的情況相同。
你的例子是另一種情況,即:
*ptr = 0xFFFFFFFF;
創建一個類型為unsigned long int
的常量0xFFFFFFFF
。 類型是unsigned
而不是int
因為該值大於最大整數值。 如果變量ptr
的類型為int*
,則編譯器需要在賦值之前將unsigned
轉換為signed
。 這會導致溢出,並且此賦值的結果將是未定義的。 雖然我不知道在從unsigned
為int
時會生成任何算術運算的編譯器。
如果ptr
被定義為int*
,並且你想要正確,那么你的行應該是:
*ptr = -1;
大多數硬件寄存器要么不是算術對象(它們可能是位字段而不是語義數字),或者如果它們確實代表一個數字,那么對它們進行語義簽名是不常見的(例如,負值對波特率除數沒有意義) )。
通常,雖然簽名類型在低級別上可能沒有區別,但它在高級別上沒有語義意義。
或許,通常用於處理硬件寄存器值的>>
運算符具有已簽名類型的實現定義行為; 因此,為了避免混合符號操作以及引入錯誤的關聯隱式轉換,您應該在大多數情況下使用unsigned。
我建議除非硬件寄存器是語義符號數字,否則你應該不僅對寄存器一致地使用無符號,而且還要在帶有寄存器操作數的表達式中使用操作數。
答案很簡單:您使用的值是無符號的(意味着文字0xFFFFFFFF是無符號的)。 您可以將其分配給任何可以保存它的數據類型 - 甚至可以使用float或double。 但是,您希望存儲無符號值並將其視為無符號值(例如,printf的%x說明符,它打印十六進制值,將其強制轉換為無符號值)。 那么,如果您的數據在整個過程中未簽名,為什么不將其容器的數據類型也取消簽名呢?
您寫入的處理器寄存器不知道或不關心編譯器如何定義值,只要寫入正確的值即可。 我贊成這個問題,因為你試圖在發布之前找到答案。
如前所述,未簽名或簽名以相同的方式存儲在硬件寄存器中。 更高級別的c將此值解釋為有符號或無符號數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.