簡體   English   中英

char 的 va_arg 故障

[英]va_arg glitches for char

我嘗試使用va_arg檢索 function 中的下一個參數。它適用於所有類型(包括 char*),但 char:

void test1(char t,...) {
  va_list args;
  va_start(args, t);
  if(t=='c') Serial.println(va_arg(args, char));
  else if(t=='n') Serial.println(va_arg(args, int));
  va_end(args);  
}

測試:

int n = 42;
char c = '?';

test1('n', n); // prints 42
test1('c', c); // prints nothing!

你能證實/解釋一下嗎? 代碼運行在 Arduino Uno,9600 波特。

小於int的 Arguments 在傳遞給可變函數之前被提升為int ,因此此類函數應將 arguments 檢索為int類型。

可變參數函數帶有一個奇怪的隱式類型提升特殊規則,稱為默認參數提升

C17 6.5.2.2/7

function 原型聲明符中的省略號導致參數類型轉換在最后聲明的參數之后停止。 默認參數提升在尾隨 arguments 上執行。

省略號是...

默認參數提升通常只在使用舊式非原型函數時使用。 因此,它們被定義為:

C17 6.5.2.2/6

如果表示被調用 function 的表達式的類型不包含原型,則對每個參數執行 integer 提升,並將類型為float的 arguments 提升為double 這些稱為默認參數提升

在您的情況下, char算作 integer 類型,以上意味着當傳遞給可變參數 function 時,它將獲得integer 提升

二進制這意味着 ASCII ? = 0x3F 被提升為int AVR 使用 16 位小尾數法,因此它在 memory 中存儲為 0x3F 0x00。問題不在於此。

相反,當您嘗試對錯誤的類型使用va_arg時,您會調用未定義的行為。 這在va_arg的文檔中有說明:

C17 7.16.1.1/2

如果沒有實際的下一個參數,或者如果類型與實際的下一個參數的類型不兼容(根據默認參數提升),則行為未定義

所以唯一可能的解決方案是將代碼更改為if(t=='c') Serial.println(va_arg(args, int)); .


與您的問題無關,在 8 位 MCU 上使用可變函數和 stdio.h 是非常糟糕的做法。 這些 function 不僅危險,它們還會消耗大量 flash 和 RAM。

此外,對於嵌入式系統,您應該始終使用stdint.h而不是默認類型 C。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM