2016-11-25 70 views
0

您好我试图建立类似用printf的参数的函数返回一个指针为char

#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; 
} 

我预计产量为0 0 1 1码,但实际上我得到0 0 0 0我做出的一个static关键字错误,返回值data_tostring()

感谢您的帮助。

回答

5

由于bufferstatic,所以两个对data_tostring(...)的调用都写入同一个缓冲区。此外,函数参数的评估顺序未详细说明,因此不保证data_tostring(&a)data_tostring(&b)之前得到评估。

固定这一点的一种可能的方式是通过使buffer作为参数传递给data_tostring

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

然后在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


如果你真的想要你本身在static buffer,您可以拨打printf两次:

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

+0

不幸的是,你的解决方案正是我想避免:) – Fabio

+0

@Fabio:为什么?如果你想使用相同的缓冲区,你需要对'printf'进行两次单独的调用。 –

+0

@Fabio:使用“静态缓冲区”替代解决方案编辑我的答案。 –

1
  • 的问题是因为在C语言中,在函数的参数从right to left评估。
  • 因此,首先对data_tostring(&b)进行评估,指针指向缓冲区char数组。
  • 接下来,对data_tostring(&a)进行评估,并且此时,存在的char值已被sprintf(buffer, "%f %f", a->x, a->y);覆盖。
  • 因此,在两次参数评估之后,两个函数评估指向具有值struct a的缓冲区char数组。这就是原因,你得到0 0 0 0

替代解决方案:

使用两分的printf()语句和seperately打印字符串或使用两个字符缓冲区的每个结构的(不推荐) 。

参考:Compilers and argument order of evaluation in C++

希望这有助于。