gcc: printf 和 long double 导致错误输出.[C - 类型转换混乱] [英] gcc: printf and long double leads to wrong output. [C - Type conversion messes up]

查看:24
本文介绍了gcc: printf 和 long double 导致错误输出.[C - 类型转换混乱]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 C 还很陌生.我尝试为 Vector 编写函数,但肯定有问题.
代码如下:

I'm fairly new to C. I try to write functions for a Vector, but there must be something wrong.
Here's the code:

/* Defines maths for particles. */

#include <math.h>
#include <stdio.h>

/* The vector struct. */
typedef struct {
    long double x, y, z;
} Vector;

Vector Vector_InitDoubleXYZ(double x, double y, double z) {
    Vector v;
    v.x = (long double) x;
    v.y = (long double) y;
    v.z = (long double) z;
    return v;
}

Vector Vector_InitDoubleAll(double all) {
    Vector v;
    v.x = v.y = v.z = (long double) all;
    return v;
}


Vector Vector_InitLongDXYZ(long double x, long double y, long double z) {
    Vector v;
    v.x = x;
    v.y = y;
    v.z = z;
    return v;
}

Vector Vector_InitLongDAll(long double all) {
    Vector v;
    v.x = v.y = v.z = all;
    return v;
}

Vector Vector_AddVector(Vector *v1, Vector *v2) {
    Vector v3;
    v3.x = v1->x + v2->x;
    v3.y = v1->y + v2->y;
    v3.z = v1->z + v2->z;
    return v3;
}

Vector Vector_AddDouble(Vector *v1, double other) {
    Vector v2;
    v2.x = v1->x + other;
    v2.y = v1->y + other;
    v2.z = v1->z + other;
    return v2;
}

Vector Vector_AddLongD(Vector *v1, long double other) {
    Vector v2;
    v2.x = v1->x + other;
    v2.y = v1->y + other;
    v2.z = v1->z + other;
    return v2;
}

void Vector_Print(Vector *v) {
    printf("X: %Lf, Y: %Lf, Z: %Lf
", v->x, v->y, v->z); //Before edit: used %ld
}

double Vector_Length(Vector *v) {
    return pow(pow(v->x, 2) + pow(v->y, 2) + pow(v->z, 2), 0.5);
}



int main() {
    Vector v = Vector_InitDoubleXYZ(2.0, 1.0, 7.0); //Before edit: (2.0d, 1.0d, 7.0d);

    Vector_Print(&v);
}

我正在使用 gcc 进行编译.在命令行中运行 vector.exe 会给我以下输出:

I'm using gcc to compile. Running vector.exe in the commandline gives me the following output:

X:0,Y:-2147483648,Z:9650176

X: 0, Y: -2147483648, Z: 9650176

我不明白为什么会这样.

and I do not understand why this is happening.

我感谢任何提示(即使是关于我的编码风格或任何可以在代码中做得更好的东西).
谢谢,

I appreciate any hints (even about my coding-style or whatever could've be done better in the code).
Thank you,

推荐答案

问题(在修复了使用整数说明符进行浮点格式化的各种问题之后)是您将 GCC 类型与不支持的 MSVC 运行时混合了解他们.

The problem (after fixing the various problems if using integer specifiers for floating point formatting) is that you're mixing GCC types with an MSVC runtime that doesn't understand them.

首先,MinGW 是一个 GCC 编译器,但它使用 MSVC 运行时来提供大部分运行时支持.这对于 printf() 函数系列意味着只有 msvcrt.dll 支持的格式说明符和 msvcrt.dll 支持的类型> 支持将起作用.但是 GCC 对此一无所知,因此它会传递自己的类型,当然,格式说明符是您在格式字符串中传递的任何内容(尽管 GCC 可能会发出并不真正适用于 msvcrt.dll 情况).见奇怪的unsigned long long int"行为 一些基于 64 位 int 的示例(我认为 msvcrt.dll 的较新版本可能已经修复了部分或全部 64 位 int 问题).

First off, MinGW is a GCC compiler, but it uses an MSVC runtime for the bulk of it runtime support. What this means for the printf() family of functions is that only the format specifiers that msvcrt.dll supports and only the types that msvcrt.dll supports will work. But GCC doesn't know anything about this, so it'll pass its own types and, of course, the format specifiers are whatever you pass in the format string (though GCC might issue warnings that don't really apply to the msvcrt.dll situation). See Strange "unsigned long long int" behaviour for some examples based on 64-bit ints (I think that newer versions of msvcrt.dll may have fixed some or all of the 64-bit int issues though).

您遇到的这个问题的另一部分是 GCC 中的 long double 与 MSVC 中的 long double 是不同的类型.GCC 对 x86 或 x64 目标上的 long double 使用 96 位或 128 位类型(参见 http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html).但是,MSVC 使用 64 位类型 - 基本上 long doublemsvcrt.dlldouble 完全相同(http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx):

The other part of this problem you're running into is that long double in GCC is a different type than long double in MSVC. GCC uses a 96-bit or 128-bit type for long double on x86 or x64 targets (see http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html). However, MSVC uses a 64-bit type - basically long double is exactly the same as double for msvcrt.dll (http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx):

以前的 16 位版本的 Microsoft C/C++ 和 Microsoft Visual C++ 支持长双精度、80 位精度数据类型.但是,在 Win32 编程中,long double 数据类型映射到 double 64 位精度数据类型.Microsoft 运行时库提供数学函数的长双精度版本只是为了向后兼容.long double 函数原型与其 double 对应的原型相同,除了 long double 数据类型替换 double 数据类型.不应在新代码中使用这些函数的 long double 版本.

Previous 16-bit versions of Microsoft C/C++ and Microsoft Visual C++ supported the long double, 80-bit precision data type. In Win32 programming, however, the long double data type maps to the double, 64-bit precision data type. The Microsoft run-time library provides long double versions of the math functions only for backward compatibility. The long double function prototypes are identical to the prototypes for their double counterparts, except that the long double data type replaces the double data type. The long double versions of these functions should not be used in new code.

所以这归结为 GCC/MinGW long double 类型将与 msvcrt.dll 中的格式化 I/O 不兼容.要么切换到使用 double 和 MinGW,或者如果你需要使用 long double 你必须将值转换为 (double)格式化 I/O 或提出您自己的格式化例程.

So what this boils down to is that the GCC/MinGW long double type will simply not be compatible with the formatted I/O in msvcrt.dll. Either switch to using double with MinGW, or if you need to use long double you'll have to cast the values to (double) for formatted I/O or come up with your own formatting routines.

另一种选择可能是在 Cygwin 下使用 GCC 编译器,我认为这将避免依赖 msvcrt.dll 进行 I/O 格式化(以依赖 Cygwin 环境为代价).

Another option might be to use the GCC compiler under Cygwin, which I think will avoid relying on msvcrt.dll for I/O formatting (at the cost of relying on the Cygwin environment).

这篇关于gcc: printf 和 long double 导致错误输出.[C - 类型转换混乱]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆