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

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

问题描述

我是相当新的C.我尝试写功能Vector的,但必须有一些错误。结果
这里的code:

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\n", 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.

我AP preciate任何提示(甚至对我的编码风格或任何可能已经在code做的更好)。结果
谢谢

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可能会发出不真正适用于<$警告C $ C> MSVCRT.DLL 情况而定)。见<一href=\"http://stackoverflow.com/questions/5997258/strange-unsigned-long-long-int-behaviour/5997384#5997384\">Strange &QUOT;无符号得到long long int&QUOT;基于64位整数的一些例子行为(我认为 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是不同的类型长双在MSVC。 GCC使用96位或128位类型长双在x86或x64目标(见<一href=\"http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html\">http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html).但是,MSVC使用64-bit类型 - 基本上长双是完全一样的双击 MSVCRT.DLL (<一个href=\"http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx\">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):

previous微软C / C ++和Microsoft Visual C ++的16位版本支持长双,80位precision数据类型。在Win32编程,然而,长双数据类型映射到双,64位precision数据类型。微软运行时库提供的数学函数长双版本只是为了向后兼容。长双函数原型是相同的原型,他们的双同行,除了长双数据类型替换双数据类型。这些函数的长双版本,不应该在新的code使用。

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.

那么,这归结为是,海湾合作委员会/ MinGW的长双键入根本不会与在 MSVCRT格式化的I / O兼容.DLL 。更换为使用双击使用MinGW,或者如果你需要使用长双你必须投中的值到(双)为格式化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和长双导致错误的输出。 [C - 类型转换搅乱]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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