0

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.

Fabio
  • 172
  • 7

2 Answers2

5

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

Vittorio Romeo
  • 82,972
  • 25
  • 221
  • 369
1
  • 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.

Community
  • 1
  • 1
eshb
  • 196
  • 1
  • 9