Jimmy liu
Jimmy liu

Reputation: 1687

Weird issue of variable function parameter

I have a print function worked well, today I want add another parameter in this function, so I added it as first parameter, but all messages with extra parameters such as "%d", are all showing incorrectly, I searched for hours trying to understand why but got nothing useful, did I make anything wrong?

I tried to add "__cdecl", it didn't work either.

If I removed first parameter "int i", then everything is working properly. It's running on OS X 10.11 with Xcode 7.1.2 a console application.

void print(int i, const char* format_str, ...) {
    // get parameters
    va_list argptr;
    char buffer[1024] = {0};
    va_start(argptr, format_str);
    vsprintf(buffer, format_str, argptr);
    // log on screen
    std::cout << (char*)buffer << std::endl;
    va_end(argptr);
}

void call_print(const char* format_str, ...) {
    print(1, format_str);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int test = 2;
    call_print("test with %d", test);
    // print(1, "test with %d", test);
    return 0;
}

OK, I edited the code to make it run-able, it looks like the warped function is where the problem came out, how should I make it right??

If call print directly, it works properly, if using call_print, it will print "test with 1606416520", if removing the first parameter "int i", it works either....

Upvotes: 1

Views: 79

Answers (2)

Jimmy liu
Jimmy liu

Reputation: 1687

It seems I have 2 ways to make it work, one is C++11's variadic template and according to my project's situation I choose second way which is simpler by moving va_start() to warp function call_print() then pass va_list to print(), finalized code would like this:

void print(int i, const char* format_str, va_list& argptr) {
    char buffer[1024] = {0};
    vsprintf(buffer, format_str, argptr);
    // log on screen
    std::cout << (char*)buffer << std::endl;
}

void call_print(const char* format_str, ...) {
    // get parameters
    va_list argptr;
    va_start(argptr, format_str);
    print(1, format_str, argptr);
    va_end(argptr);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int test = 2;
    call_print("test with %d", test);
    // print(1, "test with %d", test);
    return 0;
}

And using C++11's variadic template would like this, need add "-std=c++11" in other C++ flags:

void print(int i, const char* format_str, ...) {
    // get parameters
    va_list argptr;
    char buffer[1024] = {0};
    va_start(argptr, format_str);
    vsprintf(buffer, format_str, argptr);
    // log on screen
    std::cout << (char*)buffer << std::endl;
    va_end(argptr);
}

template< typename... Args >
void call_print(const char* format_str, Args... args) {
    print(1, format_str, args...);
    //std::snprintf( nullptr, 0, format_str, args... );
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int test = 2;
    call_print("test with %d", test);
    //print(1, "test with %d", test);
    return 0;
}

Upvotes: 0

slashmais
slashmais

Reputation: 7155

call_print is not passing the parameter 'test' on to print

skip call_print and call print directly

Upvotes: 2

Related Questions