我有一个结构:
typedef struct cbor {
cbor_type type;
uint64_t length; //x2 for maps
struct cbor* child;
struct cbor* next;
struct cbor* parent;
union {
const uint8_t* bytes;
long sint;
uint64_t uint;
double real;
} value;
} cbor;
我使用malloc初始化一个指向cbor的指针,并将length设置为0,并将uint和sint的值设置为1,并键入CBOR_INTEGER。
我有一个应该打印有关cbor struct的信息的函数:
void cbor_print_item(cbor* item){
os_printf("c2 = %d %d %d\n", item->value.sint, item->value.uint, item->length);
switch(item->type){
case CBOR_INTEGER:
os_printf("type:integer\nsval:%d\nuval:%d\nlength:%d\n", item->value.sint, item->value.uint, item->length);
os_printf("type:integer\n");
os_printf("sval:%d\n", item->value.sint);
os_printf("uval:%d\n", item->value.uint);
os_printf("length:%d\n", item->length);
break;
case CBOR_STRING:
os_printf("type:\tstring\n");
os_printf("val:\t%s\n", item->value.bytes);
os_printf("length:\t%d\n", item->length);
break;
case CBOR_REAL:
os_printf("type:\treal\n");
os_printf("length:\t%d\n", item->length);
os_printf("val:\t%f\n", item->value.real);
break;
default:
os_printf("error!\n");
}
}
但是,我没有得到预期的输出。 printf在开关中的输出应该是相同的,对吗? 我的输出是:
c2 = 1 1 0
type:integer
sval:1
uval:1
length:0
type:integer
sval:1
uval:144
length:144
我正在编写espressif的代码,因此“os_printf”,据我所知,它的工作方式是“printf”。
我真的很困惑,不知道为什么会这样。
编辑1:我知道我不应该长期使用“%d”和uint64。 问题是为什么产出不同? 我不会更改打印之间的值,因此应打印相同的值。
编辑2:这个问题不是关于联合,它们的初始化,打印uint64或更长的最佳方式。
问题是为什么
os_printf("type:integer\nsval:%d\nuval:%d\nlength:%d\n", item->value.sint, item->value.uint, item->length);
打印
type:integer
sval:1
uval:1
length:0
和
os_printf("type:integer\n");
os_printf("sval:%d\n", item->value.sint);
os_printf("uval:%d\n", item->value.uint);
os_printf("length:%d\n", item->length);
打印
type:integer
sval:1
uval:144
length:144
答案 0 :(得分:4)
您有未定义的行为,因为您尝试使用uint64_t
格式打印%d
。 printf
(以及采用可变数量参数的其他函数)需要知道参数的类型(和大小)。它从格式说明符中获取此信息。由于您提供了%d
而不是正确的格式,因此它尝试阅读int
而不是uint64_t
。请参阅this作为示例。
答案 1 :(得分:0)
使用sprintf(format, val1, val2)
将参数堆栈上的val1和val2放到sprintf上,然后sprintf将根据格式字符串从该堆栈中获取值,格式字符串盲目地在值上运行,而不知道实际大小。
所以在quintessenz:未定义的行为