簡體   English   中英

變量函數(va_arg)不適用於float,而printf有效嗎? 有什么區別?

[英]Variadic function (va_arg) doesn't work with float, while printf does? What the difference is?

我碰巧在兩年的這個問題中遇到了類似的情況:

變量函數(va_arg)不適用於float?

有人說,當我們稱之為的時候,問題是促使浮動加倍

    va_arg(arg, float)

我的問題是在這篇文章的最后,但首先讓我們來看看@ Jack在上面鏈接的問題下面的答案:

#include <stdio.h>          
#include <stdarg.h>

void foo(int n, ...)
{   
    va_list vl;
    va_start(vl, n);

    int c; 
    double val; 

    for(c = 0; c < n; c++) {
        val = va_arg(vl, double);
        printf("%f\n", val);
    }

    va_end(vl);
}


int main(void)
{
  foo(2, 3.3f, 4.4f);
  return 0;
}

輸出:

3.300000
4.400000

現在,如果我們將val = va_arg(vl, double)更改為val = va_arg(vl, float) ,我們將得到(至少我進入MSVS 2012):

36893488147419103000.000000
2.162500

我們現在回答我的問題。

在這個主題中: C / C ++ va_list沒有正確地返回參數最多的投票答案,並且它的評論說printf float提升double

但有什么區別? 如果它們都將float提升為double ,為什么printf正確地寫入值,而va_arg會給我們這樣一個鼻子惡魔?

它不是printf ,它將float參數提升為double ,它是編譯器 換句話說,當你的va_argprintf或任何其他具有可變參數數量的函數獲得控件時,所有的float都已被提升為double s; 原始float不可用於檢索。

之間的差printfva_argprintf遵循由標准設立的規則,並請求一個提升的類型(即,參數double )時,看到在格式字符串對應的格式說明。 因此,它成功地獲得了一個doublefloat值,並產生了所需的輸出。

另一方面,當va_arg調用val = va_arg(vl, float)它會忽略促銷規則,並獲得無效的表示形式。

變量參數函數的參數獲得特殊的促銷規則。

這里相關的一個是將float作為變量參數傳遞給double。 這意味着您不能將參數作為float提取,因為它已作為double傳遞。 這是由編譯器完成的,它與printf無關。

這意味着代碼val = va_arg(vl, float)無效,因為參數不是float,它是double。 如果你真的需要將傳入的值作為浮點數來處理,那么你最多可以做到

float val = (float) va_arg(vl, double)

請注意,printf的%f說明符期望參數類型為double ,而不是float

printf不接受float類型的參數。

例如, "%f"格式說明符需要double類型的參數。 "%Lf"需要long double類型的參數。 沒有格式需要一個float類型的參數(無論如何都會提升為double ,而不是printf本身,而只是因為調用variadic函數的語義)。

因此假設printf是用C實現的,並且它使用<stdarg.h>機制來讀取它的參數,在printf的實現中沒有為float類型調用va_arg()

任何嘗試為類型float調用va_arg()可變函數都將具有未定義的行為,因為這樣的函數不能有float參數。 printf有效,因為它沒有這樣做。

但有什么區別? 如果它們都將float提升為double ,為什么printf正確地寫入值,而va_arg會給我們這樣一個鼻子惡魔?

除了事實(在問題本身中說明)之外,沒有區別, printf的編碼方式是將float視為double 換句話說,在printf內部的某個地方,當格式字符串包含應該有浮點數的信息時,該函數會執行va_arg(vl, double) ,就像你一樣。

暫無
暫無

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

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