C function float argument takes different value inside the function - c

I am sure I'm missing something obvious here but just can't figure out what it is. In my repository, I have a file called ddpoly_2.c which contains a function called "ddpoly2". I call this function from the main function in tst5.c. If you look at the code in tst5_2.c, I am assigning to x a value of 2, immediately printing it and then passing it to "ddpoly2" as the third argument (which is as per what the calling pattern should be like as far as I can tell). I then immediately print x from within the function "ddpoly2". What I see is the following:
x outside: 2.000000
x inside : 0.000000
nc: 2
nd: 3
You can see that x was 2.000000 just before the function was called but it became 0.0000000 once inside the function. I must be missing something overtly obvious here but can't figure out what it is.
P.S. I compile the code using the makefile in the same directory.
EDIT: Including relevant parts of code here.
Calling the function in tst5_2.c:
int main(int argc, char *argv[])
{
//Used to determine which section gets its results printed.
float c[] = {1,1,1,0,0};
int nc = 2;
float x = 2.0;
float pd[] = {0,0,0,0,0};
int nd = 3;
printf("x outside: %f\n",x);
ddpoly2(c,nc,x,pd,nd);
}
printing it inside the function ddpoly2:
#include <stdio.h>
void ddpoly2(float c[], int nc, float x, float pd[], int nd)
{
int nnd, j, i;
float cnst = 1.0;
printf("x inside : %f\n",x);
printf("nc: %d\n",nc);
printf("nd: %d\n",nd);
}

You're calling a function without a prototype. This is illegal since 1999 but your compiler is helpful and allows this as a compatibility with old C standards.
The C standard says:
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double.
The correct solution is to:
Always have correct function prototypes.
Always enable all warnings in compilation and treat them as errors.

Related

After returning a float value from a method and trying to print it, the printed value is always wrong (although the method does works as intended)

I wrote a simple method to calculate an arithmetic mean like so:
float arithmetic_mean(int a[], int n)
{
float sum = 0;
int i;
for (i = 0; i < n; i++)
{
sum += a[i];
}
sum = sum / (float)n;
return sum;
}
I wanted to check it in main:
int main()
{
int a[] = { 1,3,5,1,6,7 };
float check = arithmetic_mean(a, 6);
printf("%f", check);
return 0;
}
even though the value the method returns is correct (=3.833333 as checked by printing it before returning it), when I try to print it in main I get 9 as the output.
I'm really new to C language and stuff like this always seems to happen with floats - I'll write a method that works and return a float - and the returned value would be something seemingly random. What am I missing here? What am I doing wrong?
The problem (which I can reproduce with MSVC) is that you are calling the arithmetic_mean function (from main) before you have defined it. Thus, the compiler uses a default definition of the function, which is that it returns an int type ... and the actual (float) value returned just happens to have a bit pattern that represents 9 when interpreted as an int.
You can leave the definition of the function where it is (after main) so long as you provide a forward declaration of the function, so that the compiler knows what the return type is:
float arithmetic_mean(int a[], int n); // Forward declaration of the function!
int main()
{
int a[] = { 1,3,5,1,6,7 };
float check = arithmetic_mean(a, 6);
printf("%f\n", check);
return 0;
}
// The actual DEFINITION (including the body) of the function can follow...
Turning on compiler warnings would have helped you spot this! For example, without the forward declaration, MSVC gives this:
warning C4013: 'arithmetic_mean' undefined; assuming extern returning
int

How to pass vectors to a function in C

I wrote a simple C program because I just got started learning how to program.
Here is the main.c file:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
float mul(float r[],float o[]){
o[0] = r[0]*11;
o[1] = r[1]*22;
o[2] = r[2]*33;
}
//==============================================================
int main(void){
float r[3];
r[0]=1;r[1]=2;r[2]=3;
float o[3];
o=mul(r,o);
return 0;
}`
My goal is to fill vector o by using the function mul; I am required to keep the definition of the variables as it is; the only thing that I am supposed to modify is the function.
When I run it by typing gcc main.c I get an error message like this:
error: incompatible types when assigning to type ‘float[3]’ from type ‘float’
o=mul(r,o);
And I have no Idea how to fix it. What am I supposed to change in my little code? as far as I learned I should pass to the function the pointers referred to the vectors but it should be the same thing of what I have done since the vector name is the pointer to the vector itself.
Thanks for your help
In C it's called an "array", not a "vector".
You can't assign a value to an array.
You have mul declared as returning a float, but it doesn't return anything - change that to void.
When you call mul, since it doesn't return anything, you don't need the o=. Just mul(r,o), will be fine.
An array is not a pointer. That said, an array does decay into a pointer to its first element in most contexts, including the function call you're using it in. Likewise, the float r[], float o[] in your mul function signature is just syntactic sugar for float *r, float *o.
o=mul(r,o);
assigns o to the return value of the mul function. But mul has no return value--it has no return statement at all, nor does it need one, because it operates directly on the arrays passed to it. Instead, just declare it void:
void mul(float r[], float o[]) {
. . .
Then call it without the assignment:
mul(r, o);

expected expression before double

Keeps saying that there is an expected expression before double int pt function
#include <stdio.h>
int pt (int a, int b)
{
int c, result;
c = (a * a) + (b + b);
result = double sqrt (double c);
return result;
}
int main (void)
{
int d, e, f;
int pt (int a, int b);
printf("type enter after input of the two legs");
scanf("%i", &d);
scanf("%i", &e);
f = pt (d,e);
printf("the hypotenuse is %i", f);
return 0;
}
Change
result = double sqrt (double c);
to
result = sqrt(c);
You don't have to cast c into a double when you pass it into the sqrt function because of implicit conversion. If you still wanted to do the cast, the correct way would be sqrt((double) c).
Also, #include <math.h> for use of the sqrt function.
Note: It's not required to cast the return type of sqrt to int (relevant since result is of type int) - however some compilers may give warnings about implicit conversion (Credit to #MattMcNabb). It can also be good practice to put the cast in to signal to other coders that the precision loss is intentional.
double sqrt (double c); is a function declaration. (It is also a function prototype). This is how you announce that a function exists, and what parameters it takes and what it returns. The word c here does not mean anything, it can be omitted.
When you want to call a function you do not repeat this info. You just give the function name, followed by a list of values, e.g. sqrt(c) .
In your code , sqrt has not been declared. Functions must be declared before they are called. It's not possible to simultaneously declare a function and call it; you have to declare it first.
(Historical note: this is true from C99 onwards; in C89 you could call an undeclared function, and the compiler would assume you wanted the function declared to return int ; this would cause undefined behaviour for any function that does not actually return int).
It is possible for you to provide your own declaration, so long as it matches the standard declaration:
double sqrt(double);
However it is a better idea to just use the standard declaration by going:
#include <math.h>
which works because the file math.h includes the line double sqrt(double); (or something equivalent).
Then you can write:
result = sqrt(c);
Note that you do not need to use any casts in relation to this function call. Since a function prototype exists, the compiler knows that even if you supply an int, it should convert that int to a double (which it knows how to do), and vice versa.
It is talking about the casting that you are doing?
your casting is complaining it should be like this:
your result is an integer, so you should be casting it to int..
but if you want to cast anything to double it should be as follow
result = (double)sqrt((double) c)
or another way is double(sqrt((double) c)
but if you want to cast it as int then
result = (int)sqrt((double) c)
or
result = int(sqrt((double) c))
hope this helps good luck

Passing a structure (pointer to structure?) to a function

Ok so, I'm trying to write a program which numerically evaluates integrals using Simpson's 3/8 rule. I'm having issues passing the values from Integral *newintegral to the simpson() function. I'm not massively confident in my understanding of structures and pointers, and I've been reviewing the lecture notes and checking online for information all day and I still can't understand why it's not working.
At the moment when I try to build my program it comes up with a number of errors, particularly: on line 46 "expected expression before Integral" and on most of 55-63 "invalid type of argument of '->' (have 'Integral') I don't understand why the first one is occurring because all my lecturers examples of this type of thing, when passing a structure to a function just have the syntax func(Struct_define_name individual_struct_name). I thought this is what I was doing with mind (Integral being the name of the structure type and i being the specific structure) but obviously not.
I think these two problems are connected so I included all of my code for context, however the lines which actually have errors are 46 and 55-63 as mentioned above. I've probably defined the structure wrong in the first place or something though.
(Incidentally the maths in the simpson() function doesn't actually work properly now anyway, but that's not something I'm concerned about)
Also I tried looking at other similar questions but I didn't understand what the other code was doing so I couldn't extrapolate how to fix my code from that. I know this isn't very relevant to other people but I really don't understand programming well enough to try and phrase my question in a general sense...
'#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct integral {
double result, limits[2];
int degree;
double coefficients[];
} Integral;
// Prototype of function that calculates integral using Simpson's 3/8 rule
double simpson(Integral i);
// function (?) which initialises structure
Integral *newintegral() {
Integral *i = malloc(sizeof *i);
double lim1_in, lim2_in;
int degree_input, n;
printf("Please enter the degree of the polynomial.\n");
scanf("%d", &degree_input);
i->degree = degree_input;
printf("Please enter the %d coefficients of the polynomial, starting\n"
"from the highest power term in the polynomial.\n", (i->degree+1));
for (n=i->degree+1; n>0; n=n-1) {
scanf("%lg", &i->coefficients[n-1]);
}
printf("Please enter the upper limit of the integral.\n");
scanf("%lg", &lim1_in);
i->limits[0] = lim1_in;
printf("Please enter the lower limit of the integral.\n");
scanf("%lg", &lim2_in);
i->limits[1] = lim2_in;
return i;
}
int main() {
Integral *i = newintegral();
simpson(Integral i);
return 0;
}
double simpson(Integral i) {
int n;
double term1, term2, term3, term4;
for (n=(i->degree); n>0; n=n-1) {
term1=(pow(i->limits[1],n)*(i->coefficients[n]))+term1;
term2=(pow(((((2*(i->limits[1]))+(i->limits[0])))/3),n)*(i->coefficients[n]))+term2;
term3=(pow(((((2*(i->limits[0]))+(i->limits[1])))/3),n)*(i->coefficients[n]))+term3;
term4=(pow(i->limits[0],n)*(i->coefficients[n]))+term4;
}
i->result = (((i->limits[0])-(i->limits[1]))/8)*(term1+(3*term2)+(3*term3)+term4);
printf("The integral is %lg\n", i->result);
return 0;
}'
You're currently passing a pointer to a function that takes a single Integral argument.
Your prototype, double simpson(Integral i); tells the compiler "declare a function called simpson that returns a double and takes a single Integral referenced by the identifier i inside the function.
However, in main() you say:
int main() {
//declare a pointer to an Integral and assign it to the return of 'i'
Integral *i = newintegral();
//call the function simpson with i.
//However, you are redeclaring the type of the function argument, so the compiler will complain.
simpson(Integral i);
return 0;
}
Your call, simpson(Integral i); will not work because you are redeclaring the type of the function argument. The compiler will state:
:46:13: error: expected expression before ‘Integral’
What you really need is for simpson() to take a pointer to Integral as its argument. You have actually already handled this inside the function, (using i->) but your function prototype is telling the compiler that you are passing the whole struct Integral as the function argument.
Solution:
Change your function prototype as follows:
double simpson(Integral *i); // function returning double taking single pointer to an Integral named i.
...and change main() to look like the following:
int main(void) { //In C main has two valid definitions:
//int main(void), or int main(int argc, char **argv)
Integral *i = newintegral();
simpson(i);
return 0;
}
So in conclusion, your understanding of pointers is correct, but not how you pass a pointer to a function.
**Sidenote:
Remember to always build your code with all warnings enabled. The compiler will give you very useful diagnostics that will help you quickly find solutions to problems like this. For GCC, as a minimum, use gcc -Wall myprogram.c
Two obvious problems:-
Line 46 : simpson(Integral i);
...should be just simpson(i);. Putting a type there is simply an error.
And this, later:
double simpson(Integral i)
.. tells the compiler to pass in Integral object yet you use the indirection operator i.e i->limits as though you'd been passed a pointer. The easiest fix is to make the function expect a pointer, like this:
double simpson(Integral *i)

Variable has value in one function, and is 0 when passed to another?

So my problem is, I am passing a variable by value (it is a float) from one function in my C code to another function. For some reason the variable is 0 after the pass. I have multiple other floats being passed by value, that are not 0 (all in the same function call), so I can't understand why this one is. It might be as simple as some typo that I am just not seeing:
int cuda_call(float *h_DataA, float *h_Kernel, int numSmooths, float kernelSum, int KERNEL_R, int KERNEL_W, int DATA_W){
printf("\n What am I here?: %f \n", kernelSum);
convolutionProgram(h_DataA, h_Kernel, numSmooths, kernelSum, KERNEL_R, KERNEL_W, DATA_W);
return 1;
}
extern "C" void convolutionProgram(float *h_DataA, float *h_Kernel, int numSmooths, float kernelSum, int KERNEL_R, int KERNEL_W, int DATA_W);
void convolutionProgram(float *h_DataA, float *h_Kernel, int numSmooths, float kernelSum, int KERNEL_R, int KERNEL_W, int DATA_W){
printf("\n what am I now? %f \n", kernelSum);
float
*d_DataA,
*d_DataB,
*d_Temp,
*d_Kernel;
.......
}
By the time I get to that second print in the called function, it is 0.
Maybe you have somehow ended up mixing calling conventions (ABIs). For instance, the first compilation unit may be performing a cdecl call, while the second one is compiled with fastcall.
http://en.wikipedia.org/wiki/X86_calling_conventions
Is it possible that you have not rebuilt the object file for one of the c files? This looks like a signature mismatch which can arrise from a function signature change without rebuilding both object files.

Resources