我是C的新手。我尝试为Vector编写函数,但肯定有问题 这是代码:
/* 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
会给出以下输出:
X:0,Y:-2147483648,Z:9650176
我不明白为什么会这样。
我感谢任何提示(甚至关于我的编码风格或代码中可以做得更好的任何提示) 谢谢,
答案 0 :(得分:13)
问题(在使用整数说明符进行浮点格式化之后修复各种问题之后)是您将GCC类型与不理解它们的MSVC运行时混合。
首先,MinGW是一个GCC编译器,但它使用MSVC运行时来获得大部分运行时支持。这对printf()
函数系列的意义在于,只有msvcrt.dll
支持的格式说明符才有效,msvcrt.dll
支持的类型才有效。但GCC对此并不了解,所以它会传递自己的类型,当然,格式说明符是你在格式字符串中传递的任何内容(尽管GCC可能会发出不真正适用于{{的警告) 1}}情况)。有关基于64位整数的一些示例,请参阅Strange "unsigned long long int" behaviour(我认为较新版本的msvcrt.dll
可能已修复了部分或全部64位int问题。)
您遇到此问题的另一部分是GCC中的msvcrt.dll
与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 double
与long double
(http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx)的double
完全相同:
以前的16位版本的Microsoft C / C ++和Microsoft Visual C ++支持长双精度,80位精度数据类型。但是,在Win32编程中,long double数据类型映射到双精度64位精度数据类型。 Microsoft运行时库提供数学函数的长双精度版本,仅用于向后兼容。长双精度原型与双精度原型相同,只是long double数据类型取代了double数据类型。不应在新代码中使用这些函数的长双精度版本。
因此,归结为GCC / MinGW msvcrt.dll
类型与long double
中的格式化I / O不兼容。切换到使用msvcrt.dll
使用MinGW,或者如果需要使用double
,则必须将值转换为long double
以用于格式化I / O或提供自己的格式化例程
另一种选择可能是在Cygwin下使用GCC编译器,我认为这将避免依赖(double)
进行I / O格式化(代价是依赖于Cygwin环境)。
答案 1 :(得分:7)
您的格式字符串与您的类型不符。 %ld
是long int
的格式说明符,而不是long double
。使用%Lg
。
答案 2 :(得分:2)
应该是:
void Vector_Print(Vector *v) {
printf("X: %Lf, Y: %Lf, Z: %Lf\n", v->x, v->y, v->z);
}
f(或g或e或G或E)表示浮点类型,大写 L表示long double
。
这是用于long double的标准 C和C ++说明符。使用小写l可能在某些实现中有效,但为什么要使程序在可行的情况下不那么便携。
注意:对于scanf函数系列,说明符略有不同。 %f(和其他)表示浮点数,%lf表示double,%Lf表示long double。
对于printf,没有float的说明符。您需要将浮点变量转换为double。
注意2:显然mingw具有一些因使用MSVC运行时导致%Lf问题而导致的不兼容性。这很奇怪,因为通常MSVC允许%lf和%Lf。
Mingw有stdio的替代实现。您可以通过#defining __USE_MINGW_ANSI_STDIO将其启用为1(see)。我不能保证它会有所帮助。我不太清楚。
更新:Michael Burr的回答解释了为什么在使用MSGC运行时与MinGW时%Lf转换失败。如果您仍然需要使用MinGW,请尝试切换到他们自己的实现。它使用真正的长双重类型。
答案 3 :(得分:0)
您是否在编译器中启用了警告?如果编译器发出警告,它可能会提示有什么问题。
答案 4 :(得分:-1)
尝试这样的事情:
Vector v;
Vector_InitDoubleXYZ(&v, 2.0d, 1.0d, 7.0d);
其中该函数定义为:
void Vector_InitDoubleXYZ(Vector *v, double x, double y, double z) {
long double t;
t = x;
v->x = t;
t=y;
v->y = t;
t=z;
v->z = t;
}