Wolfgang Roth
Wolfgang Roth

Reputation: 483

using variable number of arguments in a function call and delegating them to another function

I have got a global function which has the following signature:

void Systemfehlerprotokollieren(BYTE quelle,WORD fehlercode,WORD subfehlercode,
    BYTE klassifizierung, BYTE status,BYTE kanalnummer,DWORD detailfehler,
    WORD modulnummer,WORD location,WORD wLenZusatzText,char *pcZusatztext);

This function I want to simplify in two ways.

  1. Use variable arguments like in printf instead of pcZusatztext
  2. And thus get rid of parameter wLenZusatzText
  3. Use the original signature in a local context

So my external function (the last parameters) would look like:

ext_Systemfehlerprotokollieren(WORD location, char *form, ...);

this function then should call void Systemfehlerprotokollieren(. . . ) with its above mentioned parameters as before.

Right now I have the following code parts:

void vSystemfehlerprotokollierenText(BYTE quelle,WORD fehlercode,WORD subfehlercode,
    BYTE klassifizierung,BYTE status,BYTE kanalnummer,DWORD detailfehler,
    WORD modulnummer,WORD location,va_list args)
{
    int ret;
    char zepuf_printf_mode_lokal[ZELE];
    memset(&zepuf_printf_mode_lokal[0],0x00,ZELE);
    ret = vsnprintf_s(zepuf_printf_mode_lokal, ZELE-1,_TRUNCATE, "%s",args );
    if (ret != -1)
    {
        if (ret < 0)
        { 
            Systemfehlerprotokollieren(quelle,fehlercode,subfehlercode,
               klassifizierung,status,kanalnummer,detailfehler,
               modulnummer,location,0,NULL);
            return;
        }
    }
    Systemfehlerprotokollieren(quelle,fehlercode,subfehlercode,
        klassifizierung,status,kanalnummer,detailfehler,
        modulnummer,location,strlen(zepuf_printf_mode_lokal),zepuf_printf_mode_lokal);
}

in above function Systemfehlerprotokollieren will be called as usual

and

void SystemFehlerKG(WORD wFehlerCode, WORD wSubFehlerCode,BYTE KanalNummer,
    DWORD detailinfo2, DWORD detailinfo3, WORD programmstelle, char *form, ... )
{
    va_list args = NULL ;
    if (form != NULL)
    {
        va_start(args, form);
        vSystemfehlerprotokollierenText(SYS_FEHL_QUELLE_FLEXOS,wFehlerCode,wSubFehlerCode, 
            SYS_FEHL_KLASS_FEHLER, SYS_FEHL_STATUS_FEHLER_KOMMT_GEHT, KanalNummer, 
            (WORD)detailinfo2, (WORD)detailinfo3, programmstelle,args);
        va_end(args);
    }
    else 
        vSystemfehlerprotokollierenText(SYS_FEHL_QUELLE_FLEXOS,wFehlerCode,wSubFehlerCode, 
            SYS_FEHL_KLASS_FEHLER, SYS_FEHL_STATUS_FEHLER_KOMMT_GEHT, KanalNummer, 
            (WORD)detailinfo2, (WORD)detailinfo3, programmstelle,"");
}

This works fine, when i call the second function like this:

SystemFehlerKG(5000+TCPIP_SYS_ERROR_FKT_SEND,0,SYS_FEHL_KANAL_ALLG,
    iRet,0,SFPROG_00000,"%s","");

but I don't know what to change to get the same result with

SystemFehlerKG(5000+TCPIP_SYS_ERROR_FKT_SEND,0,SYS_FEHL_KANAL_ALLG,
    iRet,0,SFPROG_00000);

... where the last two parameters are omitted...

[Edit #1]:

I see, that printf(); doesn't work either, it must be at least printf("");

so the closest possible approach would be

SystemFehlerKG(5000+TCPIP_SYS_ERROR_FKT_SEND,0,SYS_FEHL_KANAL_ALLG,
    iRet,0,SFPROG_00000,"");

[Edit #2 as suggested by @Jan Krüger]:

void SystemFehlerKG(WORD wFehlerCode, WORD wSubFehlerCode,
    BYTE KanalNummer, DWORD detailinfo2, DWORD detailinfo3, 
    WORD programmstelle, char *form, ... )
{
    va_list args = NULL ;
    va_start(args, form);
    vSystemfehlerprotokollierenText(SYS_FEHL_QUELLE_FLEXOS,wFehlerCode,
        wSubFehlerCode, SYS_FEHL_KLASS_FEHLER,
        SYS_FEHL_STATUS_FEHLER_KOMMT_GEHT, KanalNummer, 
        (WORD)detailinfo2, (WORD)detailinfo3, programmstelle,args);
    va_end(args);
}

I dont have the code at hand right now, but i think, that this threw an exception when form was not a valid (format) string (being NULL or "").

I will tell tomorrow.

[Edit #3:]

I made the changes to my code as in edit#2. Did not work. But I found the error:

void vSystemfehlerprotokollierenText(BYTE quelle,WORD fehlercode,WORD subfehlercode, BYTE klassifizierung,BYTE status,BYTE kanalnummer,DWORD detailfehler, WORD modulnummer,WORD location,va_list args)

needs to be

void vSystemfehlerprotokollierenText(BYTE quelle,WORD fehlercode,WORD subfehlercode, BYTE klassifizierung,BYTE status,BYTE kanalnummer,DWORD detailfehler, WORD modulnummer,WORD location,char * form, va_list args)

the function SystemfehlerKGhas to be changed also to reflect the parameter form.

One thing still isnt very clear to me: If I am using the ... in my top most function and want to call another function that uses the ... signature, what must i be aware of?

Upvotes: 0

Views: 82

Answers (1)

Jan Kr&#252;ger
Jan Kr&#252;ger

Reputation: 18520

Your edit is well-spotted. In printf and friends, the format string is not part of the variadic part of the function's signature. You have to pass it separately as a normal argument.

The other important bit: you always have to pass on the va_list structure to vsnprintf_s (via your vSystemfehlerprotokollieren), even if you're sure there are no extra arguments. So, don't make the va_start and va_end conditional.

Upvotes: 1

Related Questions