【问题标题】:Function in C with unknown input data type输入数据类型未知的 C 函数
【发布时间】:2016-11-28 00:44:33
【问题描述】:

我正在尝试编写一个简单的函数,它将数字转换为给定格式的字符串,如下所示:

char * write_number(const char *format, void *number) {
    char mystring[50];
    sprintf(mystring, format, number);
    return mystring;
}

唯一的问题是这适用于整数数据类型,但不适用于浮点/双精度数据类型。无论数据类型如何,有什么方法可以使这项工作。

谢谢!

对原问题的补充:

感谢您的建议。我没能成功,这是我想要得到的完整示例。

#include <stdio.h>

void write_number(const char *format, void *number) {
    char mystring[50];
    sprintf(mystring, format, *number);
    printf("%s\n", mystring);
}

int main(void) {
    int a = 10;
    float b = 20;
    double c = 40;

    write_number("int: %03d", &a);
    write_number("float: %6.2f", &b);
    write_number("double: %6.2f", &c);

    return 0;
}

【问题讨论】:

  • 不,这个函数无论如何都坏了:它返回一个局部变量的地址。
  • 是的,是的,因为返回语句错误导致函数损坏。但为什么这适用于整数数据类型?
  • 添加这个:printf("void*=%d, int=%d, float=%d, double=%d", sizeof(void *), sizeof(int), sizeof(float ), sizeof(double));我的猜测是,你会得到 4、4、8、8(假设 float 不起作用),或者如果 float 起作用,你会得到 4、4、4、8。

标签: c string pointers type-conversion void


【解决方案1】:

sprintf 的格式字符串指定数据类型,例如,"%i" 打印整数,"%f" 打印浮点数 - 因此您需要根据数据类型更改格式字符串。

还要注意,该函数也不能保证适用于整数,因为它返回一个指向局部变量 mystring 的指针,当函数返回时,这将超出范围,并且可以随时被另一个值覆盖,因此返回的指针将指向某个随机值而不是字符串。

【讨论】:

    【解决方案2】:

    sprintf 已经处理了它的参数类型;您只需要确保传递给它的格式字符串与它的参数匹配。例如,"%f", 3.125f 格式化浮点数,"%d", 12 格式化有符号整数,"%e", 3.125 格式化双精度浮点数。尝试阅读this

    你的函数无论如何都不会工作,因为编译错误会告诉你。 mystring 被声明为堆栈上的局部变量,因此当您的函数返回时它将不复存在。

    另外,您将number地址 传递给sprintf,而不是它的。要传递值,您需要像这样取消引用它:sprintf(mystring, format, *number);

    您的函数可以使用整数类型,因为指针是整数,所以如果您调用 write_number("%d\n", 55),您将传递一个指向内存地址 55 的指针,sprintf 将解释为整数,因为 %d .如果您的 ints 和 void *s 的大小不同,这将不起作用。

    要实际传递一个指针而不是一个转换为指针的 int,请执行以下操作:

    char *str;
    float num = 8.375f;
    str = write_number("%f", &num);
    

    【讨论】:

    • 所以如果我称它为 write_number("%f", 1.0f),这行不通? (我知道不会,我已经试过了)。有什么方法可以使它工作,因为 sprintf 将数据类型转换为给定的格式?忽略return语句,我知道这是错误的以及如何解决它。
    • @Marko 好吧,它可能会使用强制转换,因为浮点数通常与整数和指针大小相同。但实际上你需要在别处声明浮点数并传递一个指向它的指针。
    • 我正在尝试为 dsPIC 微控制器编写一个函数,因此 int 和 float 数据类型的大小不同。好的,这似乎不能正常工作。我希望 sprintf 函数将数据类型本身转换为给定的格式。
    • 我也尝试过取消引用,不幸的是它不起作用。
    • dereference it like this: sprintf(mystring, format, *number); 这甚至不会编译,因为void 指针不能被取消引用,在这种情况下是void *number
    【解决方案3】:

    对于调用代码使用局部变量mystring[]的地址是未定义的行为

    “为什么这适用于整数数据类型?”

    未定义的行为并不意味着代码“不起作用”。这并不意味着如果它今天有效(使用整数),明天就会有效。这意味着该行为未定义

    【讨论】:

      猜你喜欢
      • 2022-07-20
      • 1970-01-01
      • 1970-01-01
      • 2017-07-25
      • 2021-11-26
      • 2022-01-09
      • 2018-06-13
      • 2021-12-04
      • 2013-02-26
      相关资源
      最近更新 更多