简体   繁体   中英

printf with arguments functions returning a pointer to char

Hi I tried to setup a code like

#include <stdio.h>

struct _data;
typedef struct _data data;
typedef struct _data {
    double x;
    double y;
} data;

const char* data_tostring(data* a) {
    static char buffer[255];
    sprintf(buffer, "%f %f", a->x, a->y);
    return buffer;
}

int main(){
    data a;
    data b;
    a.x = 0;
    a.y = 0;
    b.x = 1;
    b.y = 1;
    printf("%s %s \n", data_tostring(&a), data_tostring(&b));
    return 0;
}

I expected the output was 0 0 1 1, but actually I get 0 0 0 0. Did I make a mistake with the static keyword and the returning value in data_tostring() ?

Thanks for the help.

Since buffer is static , both calls to data_tostring(...) are writing to the same buffer. Furthermore, the order of evaluation of function parameters in unspecified, so there's no guarantee that data_tostring(&a) gets evaluated before data_tostring(&b) .

One possible way of fixing this is by passing buffer as an argument to data_tostring :

void data_tostring(char* buffer, data* a) {
    sprintf(buffer, "%f %f", a->x, a->y);
}

And then use multiple buffers in main :

int main()
{
    data a;
    data b;
    char a_buf[255];
    char b_buf[255];

    a.x = 0;
    a.y = 0;
    b.x = 1;
    b.y = 1;

    // Fill buffers
    data_tostring(a_buf, &a);
    data_tostring(b_buf, &b);

    printf("%s %s \n", a_buf, b_buf);
    return 0;
}

wandbox example


If you really want to use the static buffer , you can call printf twice:

int main()
{
    data a;
    data b;
    a.x = 0;
    a.y = 0;
    b.x = 1;
    b.y = 1;
    printf("%s", data_tostring(&a));
    printf(" %s \n", data_tostring(&b));
    return 0;
}

wandbox example

  • The problem is because in C language, the arguments in a function are evaluated from right to left .
  • So, first data_tostring(&b) is evaluated and the pointer points to the buffer char array.
  • Next, the data_tostring(&a) is evaluated and this time, the char values present already are overwritten by sprintf(buffer, "%f %f", a->x, a->y); .
  • So, after the two argument evaluations, the two function evaluations points to buffer char array which has the values of struct a . That's the reason you got 0 0 0 0.

Alternative solution:

Use two printf() statements and print the strings seperately or use two char buffers for each of the structs(Not recommended).

Reference: Compilers and argument order of evaluation in C++

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM