我是c的新手。我在c中编写了一个函数并将参数传递给它,但我得到了不同的答案。
功能是
void GridDim(float long1, float long2, float dx,
float lat1, float lat2, float dy,
float depth1, float depth2, float dh,
int *m, int *n, int *k)
{
*m = (int) ((long2-long1)/dx+1);
*n = (int) ((lat2-lat1)/dy+1);
*k = (int) ((depth2-depth1)/dh+1);
}
我用gcc编译它: gcc -c GridDim.c
然后我使用目标文件作为主文件并编译该文件
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int m,n,k;
GridDim(20.0,30.0,0.1,10.0,15.0,0.1,5.0,20.0,5.0,&m,&n,&k);
printf("m= %d\nn= %d\nk= %d\n", m, n, k);
return 1;
}
gcc test.c -o test GridDim.o
但我得不到正确答案。 有人知道为什么吗?
答案应该是 M = 101 N = 51 K = 4 但我得到m = 1 n = 1 k = -12
答案 0 :(得分:4)
您需要为GridDim函数声明一个函数原型,并将其包含在包含main方法的文件中。
原因是除非编译器有一个声明参数类型的函数原型,否则它会将所有浮点数提升为双精度数。在运行时,你的浮点数被提升为双精度数,然后传递给GridDim,它读取double的前半部分并将其解释为float。如果在GridDim中打印值,您将看到浮点数作为损坏的值进入。
如果您在头文件中声明方法,例如GridDim.h:
#ifndef __GRID_DIM_DOT_H__
#define __GRID_DIM_DOT_H__
extern void GridDim(float long1, float long2, float dx, float lat1, float lat2, float dy, float depth1, float depth2, float dh, int* m, int* n, int* k);
#endif/*__GRID_DIM_DOT_H__*/
...和#include它在GridDim.c中(以确保定义与声明匹配):
#include <stdio.h>
#include "GridDim.h"
void GridDim(float long1, float long2, float dx,
float lat1, float lat2, float dy,
float depth1, float depth2, float dh,
int *m, int *n, int *k)
{
printf("long1 = %10.6f\n", long1);
printf("long2 = %10.6f\n", long2);
printf("dx = %10.6f\n", dx);
printf("lat1 = %10.6f\n", lat1);
printf("lat2 = %10.6f\n", lat2);
printf("long1 = %10.6f\n", dy);
printf("depth1 = %10.6f\n", depth1);
printf("depth2 = %10.6f\n", depth2);
printf("dh = %10.6f\n", dh);
*m = (int) ((long2-long1)/dx+1);
*n = (int) ((lat2-lat1)/dy+1);
*k = (int) ((depth2-depth1)/dh+1);
}
...和#include它在Main.c中以确保调用符合声明:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "GridDim.h"
int main()
{
int m,n,k;
GridDim(20.0f,30.0f,0.1f,10.0f,15.0f,0.1f,5.0f,20.0f,5.0f,&m,&n,&k);
printf("m= %d\nn= %d\nk= %d\n", m, n, k);
return 1;
}
...然后参数将正确传递给GridDim函数。我添加了一些printf语句,以便您可以看到这一点。
如果您在Main.c中注释掉#include“GridDim.h”,那么您将看到当前版本的代码中发生了什么:
long1 = 0.000000
long2 = 0.000000
dx = -0.000000
lat1 = 0.000000
lat2 = 0.000000
long1 = -0.000000
depth1 = 0.000000
depth2 = 0.000000
dh = 0.000000
m= 1
n= 1
k= -2147483648
使用#include,输出如下所示:
long1 = 20.000000
long2 = 30.000000
dx = 0.100000
lat1 = 10.000000
lat2 = 15.000000
long1 = 0.100000
depth1 = 5.000000
depth2 = 20.000000
dh = 5.000000
m= 101
n= 51
k= 4
答案 1 :(得分:3)
您缺少功能声明。 Declare function before main()
void GridDim(float long1, float long2, float dx,
float lat1, float lat2, float dy,
float depth1, float depth2, float dh,
int *m, int *n, int *k);
一次编译两个文件
gcc main.c griddim.c -o result
./result
答案 2 :(得分:1)
正如我在评论中所说,(int)
中的类型广告C
会进行修整,例如(int)0.9 == 0
。在这里,您可能希望使用round
math.h
以下代码可以解决您的问题。
#include <math.h>
void GridDim(float long1, float long2, float dx,
float lat1, float lat2, float dy,
float depth1, float depth2, float dh,
int *m, int *n, int *k)
{
*m = round((long2-long1)/dx+1);
*n = round((lat2-lat1)/dy+1);
*k = round((depth2-depth1)/dh+1);
}
<强>编辑:强>
以下是ISO/IEC 9899:TC2
第6节标准文件中指定的内容:
6.3.1.4 Real floating和integer
1当实际浮动类型的有限值转换为_Bool以外的整数类型时, 丢弃小数部分(即,该值被截断为零)。如果值 整数部分不能用整数类型表示,行为未定义.50)
AGAING EDITED:
但是我必须说你的原始代码会在我的机器上产生你的正确答案。请注意,此问题实际上是由与机器相关的浮点数计算生成的:
假设您正在计算1.0
和5.0
:float x = 1.0 * 5.0
的产品。由于精度,您的实际结果可能是5.000002
或4.999998
,取决于运行此代码的平台。
所以当它5.000002
时,你的广播(int)x
有效,因为它只是将结果转换为5
,但是当它4.999998
时它将被转换为4
。而round
总能产生您期望的答案。
重新编辑:
哦对不起,我没有指出你问题的确切原因!您错过了功能定义。我在这里投票给@ Gangadhar的回答。
答案 3 :(得分:0)
在将值存储在变量中之前,您必须取ceil值。因为在c 0.9999值中,如果要转换为int,它将转换为零,因此在存储值之前,您必须采用ceil值。
void GridDim(float long1, float long2, float dx,
float lat1, float lat2, float dy,
float depth1, float depth2, float dh,
int *m, int *n, int *k)
{
*m = (int) (ceil((long2-long1)/dx)+1);
*n = (int) (ceil((lat2-lat1)/dy)+1);
*k = (int) ((depth2-depth1)/dh+1);
}