Reza MN
Reza MN

Reputation: 126

Passing arguments in c functions

I'm newbie in c. I have written a function in c and passes the arguments to it but I got different answers as I expect.

The function is

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);
}

I used gcc to compile it: gcc -c GridDim.c

then I used the object file for a main file and compile that file

#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

but I did not get the correct answer. Does anybody know why?

the answer should be m=101 n=51 k=4 but I got m=1 n=1 k=-12

Upvotes: 3

Views: 1556

Answers (4)

srihari
srihari

Reputation: 917

before storing the value in the variable you have to take ceil value. because in c 0.9999 value if you are converting into the int it will convert to zero so before storing the value you have to take ceil value.

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);
}

Upvotes: 0

richj
richj

Reputation: 7529

You need to declare a function prototype for your GridDim function and include it in the file that contains your main method.

The reason is that unless the compiler has a function prototype that declares the types of the arguments it will promote all floats into doubles. At run-time your floats gets promoted into doubles and then passed to GridDim which reads the first half of the double and interprets it as a float. If you print the values inside GridDim you will see that the floats come in as corrupted values.

If you declare your method in a header file, e.g. 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__*/

... and #include it in GridDim.c (to ensure that the definition matches the declaration):

#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);
}

... and #include it in Main.c to ensure that the call matches the declaration:

#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;
}

... then the arguments will be passed correctly to the GridDim function. I added some printf statements so that you can see this.

If you comment out the #include "GridDim.h" in Main.c then you will see what is happening in your current version of the code:

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

With the #include the output looks like this:

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

Upvotes: 4

starrify
starrify

Reputation: 14781

As I've said in the comments, the type cast (int) in C does trimming, e.g. (int)0.9 == 0. Here you may want to use the function round provided by math.h

The following code solves your problem.

#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);
}

EDITED:

Here's it's specified in the standard document, in Section 6 of ISO/IEC 9899:TC2:

6.3.1.4 Real floating and integer

1 When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.50)

AGAING EDITED:

However I have to say that your original code produces your-correct-answers on my machine. Please notice this problem is actually generated by the machine-dependent floating point number calculation:

Assuming your're calculating the product of 1.0 and 5.0: float x = 1.0 * 5.0. Here due to the precision, your actual result MAY BE 5.000002 or 4.999998, depends on the platform that runs this code.

So when it's 5.000002, your type cast (int)x works since it just cast the result to 5, however when it's 4.999998 it would be casted to 4. And round would always produce your expected answers.

AGAIN EDITED:

Oh sorry I'm not pointing the exact reason of your problem! You're missing the function definition. Here I vote for @Gangadhar's answer.

Upvotes: 1

Gangadhar
Gangadhar

Reputation: 10526

You are missing declaration of function. 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);

And compile both files at a time

gcc main.c griddim.c -o result
./result

Upvotes: 3

Related Questions