4

不久前,我正在寻找导致错误数字数据写入日志文件的错误。原来问题在于该代码等效于以下内容:

int main(void) {
    struct {
        double a;
        int b;
    } s = { 1, 2 };

    printf("%lf\n", s.a);
    printf("%lf\n", s.b);
}

正在输出

1.000000
1.000000

显然printf期待浮点寄存器中的第二个值,而不是堆栈中的值。为了防止将来发生此类错误,是否应该强制转换所有 printf 参数以确保它们确实是预期的类型?

4

5 回答 5

5

According to C99 standard. Mismatch in format specifier and datatype of actual data to be printed is Undefined behavior

Here b is and int so if you give "%d" in second printf() function. It will print the correct value otherwise Behavior is Undefined

From c99

7.19.6 9 If a conversion specification is invalid, the behavior is undefined.242) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined

于 2013-08-30T10:46:53.817 回答
2

是否应该强制转换所有printf参数以确保它们确实是预期的类型?

一般不会。您应该为您传递的每个参数使用格式说明符和参数类型的正确组合。当然,如果您有一个“错误类型”的参数(例如int,您想使用浮点格式说明符打印),那么它需要以某种方式进行转换,这通常意味着强制转换。printf但是, “以防万一”将大量演员分散在您的线路上并不是正确的解决方案。

请注意,编译器不需要“理解” printf(或scanfstrftime等)的格式字符串,因此编译器只需根据一组限制列表传递参数(float转换为double,短整数(charshort)被转换为int,以及其他一些类似的东西)。然后归结为printf整理您拥有的东西。当然,如果您没有正确的参数格式规范,那么printf可能确实会在错误的位置查找参数。

因此,总而言之,您需要匹配printf. 如果这意味着您偶尔需要演员表,那么是的,请使用演员表。但这不应该是“常规的事情”。

于 2013-08-30T11:06:20.610 回答
2

是否应该强制转换所有 printf 参数以确保它们确实是预期的类型?

如果类型与预期不同,的。 如果您为编译器启用警告,它会告诉您这一点。

我怀疑您的行为是相信 printf 的模板说明符指示您希望将值显示为哪种样式。这部分正确,并且(通过强制转换)可以用于主要目的,但主要目的是向 printf 指示正在考虑哪种值

所以,如果你有一个整数类型,你可能会使用%d,但不是%f,因为%f这是一个谎言,而对计算机撒谎是一件棘手的事情。如果 的目的%f是因为您希望打印带有小数位的值,那么您应该强制转换它;这会将整数值正确转换为浮点数。(您也可以只使用%d.000000,因为整数没有分数)。

否则,您应该只使用适合该类型的说明符。

于 2013-08-30T10:54:28.300 回答
1

在您的代码中,您的代码printf采用整数 2 的内部二进制表示并将其视为浮点数。

而不是cast all printf parameters to be sure that they really are of the expected type您应该确保输入的任何说明符printf都是正确的类型。你知道那s.b是一个int为什么要使用%f

于 2013-08-30T10:55:48.557 回答
0

老实说,如果将数据类型从 struct { double a; 诠释 b; } s = { 1, 2 }; 结构 { 双 d_a; 诠释 n_b; } s = { 1, 2 };

即使您不使用匈牙利符号,也只需在变量中使用一些标签来传递类型信息。那么当你输入 printf("%lf\n", s.n_b); 时,很容易找到这里的陷阱。

C 类型转换在不同的平台上有不好的副作用。他们狡猾而草率。如果有其他方法可以解决问题,请不要使用类型转换。

于 2013-08-30T13:52:19.267 回答