宏定义类型的c printf

宏定义类型的c printf,c,C,我在if宏中有一个typedef,类似于: #ifdef BLA_BLA typedef int typeA #elseif typedef double tyeA #endif printf("%d" , a); printf("%l" , a); 我想知道当我为这个案例编写printf时,最好的方法是什么?%d或%l 我知道我也可以在宏中定义固定字符串。但是这是最好的方法吗?也使用宏定义格式字符串 #ifdef BLA_BLA typedef int typeA; #define FOR

我在if宏中有一个typedef,类似于:

#ifdef BLA_BLA
typedef int typeA
#elseif 
typedef double tyeA
#endif
printf("%d" , a); printf("%l" , a);
我想知道当我为这个案例编写printf时,最好的方法是什么?%d或%l


我知道我也可以在宏中定义固定字符串。但是这是最好的方法吗?

也使用宏定义格式字符串

#ifdef BLA_BLA
typedef int typeA;
#define FORMAT "%d"
#elseif 
typedef double typeA;
#define FORMAT "%f"
#endif

...
typeA a = ...;
printf("Hello " FORMAT " there", a); printf(FORMAT , a);

也可以使用宏定义格式字符串

#ifdef BLA_BLA
typedef int typeA;
#define FORMAT "%d"
#elseif 
typedef double typeA;
#define FORMAT "%f"
#endif

...
typeA a = ...;
printf("Hello " FORMAT " there", a); printf(FORMAT , a);

还有另一种选择-定义一个简短的助手函数,这样您就不必在代码中到处散布ifdef:

#ifdef BLA_BLA
typedef int typeA
#else
typedef double typeA
#endif

inline void print_typeA(const typeA val) {
#ifdef BLA_BLA 
  printf("%d" , val); 
#else
  printf("%e" , val);
#endif
}

somefunc()
{ typeA xyz;

  print_typeA(xyz);
}

还有另一种选择-定义一个简短的助手函数,这样您就不必在代码中到处散布ifdef:

#ifdef BLA_BLA
typedef int typeA
#else
typedef double typeA
#endif

inline void print_typeA(const typeA val) {
#ifdef BLA_BLA 
  printf("%d" , val); 
#else
  printf("%e" , val);
#endif
}

somefunc()
{ typeA xyz;

  print_typeA(xyz);
}

是否确实要将类型定义为整数或浮点?它们都是数字的,但它们的行为在许多方面是如此的不同,以至于编写在任何一种情况下都能正确工作的代码都是困难的

在许多情况下,您可以转换为足够宽的类型,以覆盖两种可能类型的范围。一个简单的例子:

#include <stdio.h>

#ifdef BLA_BLA
typedef int num_type;
#else
typedef long num_type;
#endif

int main(void) {
    num_type x = 42;
    printf("x = %ld\n", (long)x);
    return 0;
}
更一般地说,您可以分别使用%jd或%ju转换为在或中定义的intmax_t或uintmax_t


通过将所有内容转换为长双精度几乎可以完成相同的操作,但对于大的整数值,这可能会失去精度。

是否确实要将类型定义为整数或浮点?它们都是数字的,但它们的行为在许多方面是如此的不同,以至于编写在任何一种情况下都能正确工作的代码都是困难的

在许多情况下,您可以转换为足够宽的类型,以覆盖两种可能类型的范围。一个简单的例子:

#include <stdio.h>

#ifdef BLA_BLA
typedef int num_type;
#else
typedef long num_type;
#endif

int main(void) {
    num_type x = 42;
    printf("x = %ld\n", (long)x);
    return 0;
}
更一般地说,您可以分别使用%jd或%ju转换为在或中定义的intmax_t或uintmax_t


几乎可以通过将所有内容转换为长双精度来完成相同的工作,但这可能会丢失大整数值的精度。

如果是我,我不会直接将typeA参数传递给printf;我将创建另一个返回typeA值的字符串表示形式的函数,并将该字符串传递给printf或任何其他需要显示该字符串的函数

char *formatTypeA(typeA val, char *buf, size_t len)
{
  #ifdef BLA_BLA
  #define FORMATCHAR d
  #else
  #define FORMATCHAR f
  #endif

  char formatStr[SIZE]; // where SIZE is large enough to handle the longest
                        // possible size_t value plus "%" plus the format
                        // character plus the 0 terminator
  sprintf(formatStr, "%%%zu" FORMATCHAR, len - 1); 
  sprintf(buf, formatStr, val);
  return buf;
}

int main(void)
{
  typeA foo;
  char output[10];
  ...
  printf("foo = %s\n", formatTypeA(foo, output, sizeof output));
  ...
}
也许有更好的办法

编辑


顺便说一句,这是我不经常使用typedef的原因之一;如果表示像在本例中那样重要,那么您真的不想对使用它的人隐藏该信息。

如果是我,我不会直接将typeA参数传递给printf;我将创建另一个返回typeA值的字符串表示形式的函数,并将该字符串传递给printf或任何其他需要显示该字符串的函数

char *formatTypeA(typeA val, char *buf, size_t len)
{
  #ifdef BLA_BLA
  #define FORMATCHAR d
  #else
  #define FORMATCHAR f
  #endif

  char formatStr[SIZE]; // where SIZE is large enough to handle the longest
                        // possible size_t value plus "%" plus the format
                        // character plus the 0 terminator
  sprintf(formatStr, "%%%zu" FORMATCHAR, len - 1); 
  sprintf(buf, formatStr, val);
  return buf;
}

int main(void)
{
  typeA foo;
  char output[10];
  ...
  printf("foo = %s\n", formatTypeA(foo, output, sizeof output));
  ...
}
也许有更好的办法

编辑


顺便说一句,这是我不经常使用typedef的原因之一;如果表示法很重要,例如在本例中,那么您确实不想对使用它的人隐藏该信息。

在实际应用程序中,格式字符串很可能会更长。@ThiefMaster-同意,但是,该建议的目的是不必每次打印值时都使用ifdef,这与OP的例子是一致的。涉及其他值和字符串的更复杂的格式设置显然需要额外的工作…在实际应用程序中,格式字符串很可能更长。@ThiefMaster-同意,但是,该建议的目的是不必在每次打印值时都使用ifdef,并且与OP的示例一致。涉及其他值和字符串的更复杂格式显然需要额外工作…%l不正确;double的格式为%f、%g或%e,具体取决于您希望如何处理指数。%l不正确;double的格式为%f、%g或%e,具体取决于您希望如何处理指数。