[英]C++ Standard Library: How to write wrappers for cout, cerr, cin and endl?
[英]How can I print values in C without specifying their types, like done with “cerr << (A) << endl” in C++?
在C ++中,有
#define DEBUG(A) cerr << (A) << endl;
我可以发送任何东西,它可以打印出来。 但是,在C中,我必须用%d,%c或%s等指定它的类型。但我不想一直写它的类型,我想使用类似cerr
fprintf
。 我怎样才能做到这一点?
例如:在C中
#define DEBUG(A) X // X is what I want to write
...
// in function, when I put
DEBUG(5); // I just want to print 5
// or, with same statement, when I say
DEBUG('a'); // output : a
您可以使用GNU C语言扩展 :
#define DEBUG(x) \
({ \
if (__builtin_types_compatible_p (typeof (x), int)) \
fprintf(stderr,"%d\n",x); \
else if (__builtin_types_compatible_p (typeof (x), char)) \
fprintf(stderr,"%c\n",x); \
else if (__builtin_types_compatible_p (typeof (x), char[])) \
fprintf(stderr,"%s\n",x); \
else \
fprintf(stderr,"unknown type\n"); \
})
这些很好:
DEBUG("hello"); //prints hello
DEBUG(11110); //prints 11110
但对于字符,你应该使用左值,否则它的类型将是“int”:
char c='A';
DEBUG(c); // prints A
DEBUG('A'); // prints 65
你不能以你想要的方式使用fprintf()
。 欢迎来到C.
C ++ I / O流运算符是类型安全的,并使用运算符重载来实现它们的魔力。 这在C中不可用,因此您必须坚持使用不安全的格式字符串方法。
原则上,你不能,因为C没有重载机制。
但是,您可以定义许多宏,例如:
#define DEBUG_INT(x) fprintf(stderr, "%d\n", (x))
#define DEBUG_CHAR(x) fprintf(stderr, "%c\n", (x))
没有办法摆脱转换规范,但是如果你有一个C99编译器,你可以使用__VA_ARGS__
并使它更容易一些,例如,
#include <stdio.h>
#define DEBUG(fmt, ...) fprintf(stderr, (fmt), __VA_ARGS__)
int main(void) {
int foo = 42;
char *t = "foobar";
DEBUG("%s:%d\n", t, foo);
return 0;
}
在C中,您无法可靠地确定对象的类型。 因此,您必须引入一些支持泛型编程的机制,例如将所有对象封装在包含类型信息的结构中:
enum {type_int, type_double, type_string, /* ... */ } type_t;
struct {
type_t type;
void *obj;
} generic_type;
现在,您可以切换((generic_type)my_object).type
。 这可能不是你想要的。
但是,有一个简单的技巧来判断宏参数是字符串文字还是其他东西。 使用宏引用字符'#',您可以将宏参数转换为字符串:
#define DEBUG(x) if (#x[0] == '"') printf("%s\n", x); else printf("%d\n", x)
现在您可以执行以下操作:
DEBUG("foo bar"); // prints "foo bar"
DEBUG(23); // prints "23"
在缺点方面,这不会让你区分例如int
s和float
s。 此外,指向char的指针不被识别为字符串:
char *foo = "bar";
DEBUG(foo); // prints the value of foo, not the string pointed to by foo
double salary;
DEBUG(salary); // prints (int)salary, not (double)salary
在某些机器上, sizeof(double) != sizeof(int)
。 这可能有助于进一步区分不同类型的宏参数,但它肯定不可移植。
一般来说,如果不对通用编程支持做出一些认真努力同时保持可移植性,您将无法完全解决此问题。
我的建议:简单地习惯格式说明符。
您可以只执行以下__VA_ARGS__
,而不是使用__VA_ARGS__
:
#define DEBUG(x...) fprintf(stderr, x)
与GCC内置方法不同,此方法允许您混合匹配 - 您可以打印“string =”,而不是一次只打印一种类型。 您也不会以这种方式遇到大小和类型不兼容 - 它与fprintf基本相同,除非能够在构建时被排除!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.