Changing int to double changes my result to zero - c

If I leave all variables as int I get 32. The division is supposed to give me 32.5 so I thought that changing everything to double would do it, but it just gives me zero...
Here is the code (everything in int):
#include <stdio.h>
#include <stdlib.h>
void sommeTableau(int tableau[], int tailleTableau, int *x, int *average);
int main(int argc, char *argv[])
{
int tableau[4] = {30, 50, 50};
int *x = 0;
int *average = 0;
const int tailleTab = 4;
sommeTableau(tableau, tailleTab, &x, &average);
printf("The average is %d\n", average);
return 0;
}
void sommeTableau(int tableau[], int tailleTableau, int *x, int *average)
{
int i = 0;
for (i = 0 ; i < tailleTableau ; i++)
{
*x = *x + tableau[i];
}
*average = *x/tailleTableau;
}
So this works and gives me 32... Now if I change everything to double and %d to %f in the printf function, it gives me zero and I don't understand why...

There is lots of mistakes in your code. I corrected all of them
#include <stdio.h>
#include <stdlib.h>
void sommeTableau(int tableau[], int tailleTableau, int *x, double *average);
int main(int argc, char *argv[])
{
int tableau[4] = {30, 50, 50};
int x = 0;
double average = 0;
const int tailleTab = 4;
sommeTableau(tableau, tailleTab, &x, &average);
printf("The average is %lf\n", average);
return 0;
}
void sommeTableau(int tableau[], int tailleTableau, int *x, double *average)
{
int i = 0;
for (i = 0 ; i < tailleTableau ; i++)
{
*x = *x + tableau[i];
}
*average = (double)(*x)/(double)tailleTableau;
}

You are passing x and average as null pointer. Thats why your code is giving segmentation fault.
As per you describtion please check(http://codepad.org/z8fVUTe5).
#include <stdio.h>
#include <stdlib.h>
void sommeTableau(int tableau[], int tailleTableau, int *x, int *average);
int main(int argc, char *argv[])
{
int tableau[4] = {30, 50, 50};
int x = 0;
int average = 0;
const int tailleTab = 4;
sommeTableau(tableau, tailleTab, &x, &average);
printf("The average is %d\n", average);
return 0;
}
void sommeTableau(int tableau[], int tailleTableau, int *x, int *average)
{
int i = 0;
for (i = 0 ; i < tailleTableau ; i++)
{
*x = *x + tableau[i];
}
*average = *x/tailleTableau;
}
Output:-
The average is 32

One of your problems lies here:
int *x = 0;
int *average = 0;
sommeTableau(tableau, tailleTab, &x, &average);
Those first two lines should be:
int x = 0;
int average = 0;
This is evident from the warnings you should be getting, assuming you're using a decent compiler:
qq.c: In function ‘main’:
qq.c:13: warning: passing argument 3 of ‘sommeTableau’ from incompatible pointer type
qq.c:4: note: expected ‘int *’ but argument is of type ‘int **’
qq.c:13: warning: passing argument 4 of ‘sommeTableau’ from incompatible pointer type
qq.c:4: note: expected ‘int *’ but argument is of type ‘int **’
In addition, you don't need _everything to be a double, just the average, so you should only change the type of that variable and match that with the parameters passed to the function.
It will also be necessary to cast the total *x to a double before doing the division, so that it knows you don't mean integer division.
With those changes, the output changes from:
The average is 4.000000
(for me) to the correct:
The average is 32.500000
See the following program for more detail:
#include <stdio.h>
#include <stdlib.h>
void sommeTableau(int tableau[], int tailleTableau, int *x, double *average) {
int i;
for (i = 0 ; i < tailleTableau ; i++)
*x = *x + tableau[i];
*average = ((double)(*x))/tailleTableau;
}
int main (void) {
int tableau[4] = {30, 50, 50};
int x = 0;
double average = 0;
const int tailleTab = 4;
sommeTableau(tableau, tailleTab, &x, &average);
printf("The average is %lf\n", average);
return 0;
}

int *x = 0;
int *average = 0;
This is defining two pointers and setting the pointers to zero -- which, in a pointer context translates to a null pointer. So, you have to pointers to nothing.
sommeTableau(tableau, tailleTab, &x, &average);
Here, you're passing the addresses of those pointers to the function, so the function is really receiving an int **.
printf("The average is %d\n", average);
This is then taking the value of the pointer -- the address its holding -- and (probably) treating that bit pattern as an int. This is technically undefined behavior, but on many machines, a pointer it enough like an int for it to appear to work. The same will almost never be true with a floating point number though.
What you want to do here is define two ints (or two doubles) and pass their addresses to your function:
double x=0.0, average=0.0;
sommeTableau(tableau, tailleTab, &x, &average);
// ...
printf("%f, %f\n", x, average);

It doesn't actually work.
Here you define x and average as NULL pointers to int:
int *x = 0;
int *average = 0;
And here instead of pointers to int you pass pointers to pointers to int:
sommeTableau(tableau, tailleTab, &x, &average);
Which is clearly wrong. You should enable compiler warnings to see such problematic places and correct them.
Here the correction would be:
int x = 0;
int average = 0;
Now, here:
printf("The average is %d\n", average);
You are lying to printf() about what you're going to give it (an int, because of %d), but you're actually giving it a pointer to int. The above correction fixes this. If you lie to printf() about the type of some parameter, anything can happen. If your compiler is gcc and you enable warnings, you can spot this kind of problems as well.

Something is terribly wrong here -- you're defining x and average as pointer variables in main, which if you are lucky is the same size as an int, but may result in undefined behavior.
Remove the * from the local variable declarations of x and average in main and it may actually work.
Also, in sommeTableau, both operands of the division (*x and tailleTableau) are int, so integer division is performed and the remainder discarded prior to assignment to *average.

Related

Why is this function parameter not treated as local variable to this function?

I have a function which returns an integer pointer type:
int* f(int a, int b){
int *result;
result = &a;
*result += b;
return result;
}
and when I call this on main:
int main(){
int a = 5;
int b = 2;
int *result = f(a,b);
printf("The result is: %d \n", *result);
return 0;
}
It gives me the correct output(in this case 7). I was under the impression that by assigning the address of the parameter a to result I would get a segmentation fault when I ran this function.
My assumption is that C treats function parameters as local in scope to the function definition. But, I see that this is not the case so why is this specific program working ?
I'm using Code::Blocks 16.01 with gcc compiler.
Just because it works on your machine doesn't mean it isn't undefined behaviour. This works by fluke, but it's invalid.
It may produce the correct result because that stack is not overwitten or otherwise mangled by the time you do something later on.
For example, if you make another function call:
#include <stdio.h>
#include <stdlib.h>
int noop(int x, int y) {
return x + y;
}
int* f(int a, int b){
int *result;
result = &a;
*result += b;
return result;
}
int main(){
int a = 5;
int b = 2;
// Do something with undefined behaviour
int *result = f(a,b);
// Do something else which uses the stack and/or the same memory
int x = 10;
int y = 11;
int z = noop(x, y);
printf("The result is: %d \n", *result);
return 0;
}
Now the output gets stomped with the definition of x which coincidentally takes the same piece of memory so the output is 10. As this is undefined behaviour, though, anything could happen, including a crash.

Cast void pointer to double without knowing its type in C

I need to write a function which takes as parameters a void pointer (representing an array) and an integer which represents the length of the array. In the function, I need to cast this void pointer into a double one. The problem is that the void pointer can represent an array of integers or floats or doubles.
So the following is obviously not working in case the void pointer represents an array of integers or floats:
void foo(void *v,int n){
double *values;
values=(double*)v;
for(i=0;i<n;i++)
printf("%f\n",values[i]);
}
so this will print the correct output:
foo((double[]){1,2,3,4},4);
and this will print a wrong output:
foo((int[]){1,2,3,4},4);
foo((float[]){1,2,3,4},4);
So... can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles? And is it necessary to have the length of the array or I can calculate it somehow?
P.s. without using callbacks
can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles?
No, you cannot. You need to pass the type information somehow.
And is it necessary to have the length of the array or I can calculate it somehow?
It's necessary to pass the length.
You can "hide" the information inside a struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum etype { INTEGER, FLOAT, DOUBLE };
struct data {
void *values;
size_t n;
enum etype type;
};
void foo(struct data *x) {
int *xd = x->values;
float *xf = x->values;
double *xg = x->values;
for (int k = 0; k < x->n; k++) {
switch (x->type) {
default: printf("%g ", xg[k]); break;
case FLOAT: printf("%f ", xf[k]); break;
case INTEGER: printf("%d ", xd[k]); break;
}
}
puts("");
}
int main(void) {
struct data x;
x.values = malloc(4 * sizeof(int));
((int*)(x.values))[0] = 42;
((int*)(x.values))[1] = -1;
((int*)(x.values))[2] = 0;
((int*)(x.values))[3] = 999;
x.n = 4;
x.type = INTEGER;
foo(&x);
x.values = calloc(4, sizeof(float));
x.type = FLOAT;
float tmp = 3.14159;
memcpy(((float*)(x.values))+1, &tmp, sizeof (float));
foo(&x);
free(x.values);
x.values = calloc(4, sizeof(double));
x.type = DOUBLE;
((double*)(x.values))[2] = 2.7182818;
foo(&x);
free(x.values);
}
See code running on ideone

Pointers' array in a function does not showing on the correct values of the array used in call

I have the following program.
#include <stdio.h>
double getAverage(int *arr[], int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i)
{
printf("%d %d\n", i, arr[i]);
sum = sum + arr[i];
}
printf("%d\n", sum);
avg = (double)sum / size;
return avg;
}
int main ()
{
/* an int array with 5 elements */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* pass pointer to the array as an argument */
avg = getAverage( balance, 5 ) ;
/* output the returned value */
printf("Average value is: %f\n", avg );
return 0;
}
It's output is not correct. When I print the *arr[] values, the are not the same as the balance value. Do you know why and how I can fix this program?
0 1000
1 3
2 50
3 0
4 0
256992
Average value is: 51398.400000
Your function is declared like
double getAverage(int *arr[], int size)
That is, the first argument is supposed to be an array of pointers to int.
Then you call it as
getAverage( balance, 5 )
where balance is an array of int, which decays to a pointers to its first element (i.e. balance is equal to &balance[0]). This have the type int *.
The two types are mismatching, which the compiler should have warned you about.
The solution is to fix the function argument:
double getAverage(int *arr, int size)
The problem is here:
double getAverage(int *arr[], int size) {
You're passing a pointer to an array. That decays to a double pointer (a int**). You're using it like an int*, however. As a result, the pointer arithmetic under the hood is wrong. Change it to this:
double getAverage(int arr[], int size) {
It looks like on your setup, the pointers are twice as big as your ints, which is why it's always skipping a value (and ends up accessing invalid memory in the end).
If your compiler did not issue any warning for this code, try to see if you can set it to be more strict with warnings.

Cannot access memory

I'm getting a segfault, and when I debug it I get the following message:
Cannot access memory at 0x806d128
I attempted to set a watchpoint there to monitor the address, but the response gdb gave me was:
Cannot watch constant value '0x806d128'
However when I print the pointer containing the address it recognises the struct that I've got stored there:
(body *) 0x806d128
According to gdb the error occurs in addForce(), which is a bit odd since that address is accessed earlier in init()
Here's the relevant code:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define prec float
prec gdt = 0.0001;
typedef struct {
float Fx, Fy, vx, vy, mass;
int posX, posY;
} body;
void addForce(body* a, body* b){
int xa=(*a).posX, ya=(*a).posY;
int xb=(*b).posX, yb=(*b).posY;
float F=(*a).mass * (*b).mass * gdt /(pow(xa-xb, 2)+pow(ya-yb, 2));
float v=atan((ya-yb)/(xa-xb));
float Fx=cos(v)/F, Fy=sin(v)/F;
(*a).Fx+=Fx;
(*a).Fy+=Fy;
(*b).Fx-=Fx;
(*b).Fy-=Fy;
}
int newRandInt(int bot, int top){
return bot + (rand() % (top++));
}
prec newRand()
{
prec r = (prec)((double)rand()/(double)RAND_MAX);
return r;
}
void init(int N, body* star){
for(int i=0; i<N;i++){
star[i].posX = newRandInt(0, 800);
star[i].posY = newRandInt(0, 800);
star[i].Fx = newRand();
star[i].Fy = newRand();
star[i].vx = newRand();
star[i].vy = newRand();
star[i].mass = newRand();
}
}
int main(int argc, char* argv[]) {
int N = 200;
body* stars = malloc(sizeof(body)*N);
init(N, stars);
for(int j1=0; j1<N; j1++){
for(int j2=0; j2<N-1; j2++){
if(j1!=j2){
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
}
}
}
return 0;
}
This call to addForce is not what you want:
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
You don't want the sizeof(body) expression in this call to addForce. The call you probably want is:
addForce(stars+j1, stars+j2);
stars is an array of body so you can reference individual stars with
body *p = &stars[i]
or just
body *p = stars + i
Both of these have the type body*
In this line:
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
when you do sizeof(body) it evaluates to size of structure in bytes, then it is multiplied by j1. So you have some_nr*j1.
That value is added to stars, which is pointer to body.
Pointer arithmetics evaluate some_nr*j1*sizeof(pointer to body).
What you want to do is stars+j1 alone, which will be correctly evaluated as pointer to body and added to arrays.
The same happends in the second part of addForce.
What you missed is that with pointers arithmetics the second operand of '+' operator is recalculated to match size of pointee.

C pass int array pointer as parameter into a function

I want to pass the B int array pointer into func function and be able to change it from there and then view the changes in main function
#include <stdio.h>
int func(int *B[10]){
}
int main(void){
int *B[10];
func(&B);
return 0;
}
the above code gives me some errors:
In function 'main':|
warning: passing argument 1 of 'func' from incompatible pointer type [enabled by default]|
note: expected 'int **' but argument is of type 'int * (*)[10]'|
EDIT:
new code:
#include <stdio.h>
int func(int *B){
*B[0] = 5;
}
int main(void){
int B[10] = {NULL};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
now i get these errors:
||In function 'func':|
|4|error: invalid type argument of unary '*' (have 'int')|
||In function 'main':|
|9|warning: initialization makes integer from pointer without a cast [enabled by default]|
|9|warning: (near initialization for 'B[0]') [enabled by default]|
||=== Build finished: 1 errors, 2 warnings ===|
In your new code,
int func(int *B){
*B[0] = 5;
}
B is a pointer to int, thus B[0] is an int, and you can't dereference an int. Just remove the *,
int func(int *B){
B[0] = 5;
}
and it works.
In the initialisation
int B[10] = {NULL};
you are initialising anint with a void* (NULL). Since there is a valid conversion from void* to int, that works, but it is not quite kosher, because the conversion is implementation defined, and usually indicates a mistake by the programmer, hence the compiler warns about it.
int B[10] = {0};
is the proper way to 0-initialise an int[10].
Maybe you were trying to do this?
#include <stdio.h>
int func(int * B){
/* B + OFFSET = 5 () You are pointing to the same region as B[OFFSET] */
*(B + 2) = 5;
}
int main(void) {
int B[10];
func(B);
/* Let's say you edited only 2 and you want to show it. */
printf("b[0] = %d\n\n", B[2]);
return 0;
}
If you actually want to pass an array pointer, it's
#include <stdio.h>
void func(int (*B)[10]){ // ptr to array of 10 ints.
(*B)[0] = 5; // note, *B[0] means *(B[0])
//B[0][0] = 5; // same, but could be misleading here; see below.
}
int main(void){
int B[10] = {0}; // not NULL, which is for pointers.
printf("b[0] = %d\n\n", B[0]);
func(&B); // &B is ptr to arry of 10 ints.
printf("b[0] = %d\n\n", B[0]);
return 0;
}
But as mentioned in other answers, it's not that common to do this. Usually a pointer-to-array is passed only when you want to pass a 2d array, where it suddenly looks a lot clearer, as below. A 2D array is actually passed as a pointer to its first row.
void func( int B[5][10] ) // this func is actually the same as the one above!
{
B[0][0] = 5;
}
int main(void){
int Ar2D[5][10];
func(Ar2D); // same as func( &Ar2D[0] )
}
The parameter of func may be declared as int B[5][10], int B[][10], int (*B)[10], all are equivalent as parameter types.
Addendum: you can return a pointer-to-array from a function, but the syntax to declare the function is very awkward, the [10] part of the type has to go after the parameter list:
int MyArr[5][10];
int MyRow[10];
int (*select_myarr_row( int i ))[10] { // yes, really
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
This is usually done as below, to avoid eyestrain:
typedef int (*pa10int)[10];
pa10int select_myarr_row( int i ) {
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
In new code assignment should be,
B[0] = 5
In func(B), you are just passing address of the pointer which is pointing to array B. You can do change in func() as B[i] or *(B + i). Where i is the index of the array.
In the first code the declaration says,
int *B[10]
says that B is an array of 10 elements, each element of which is a pointer to a int. That is, B[i] is a int pointer and *B[i] is the integer it points to the first integer of the i-th saved text line.
Make use of *(B) instead of *B[0].
Here, *(B+i) implies B[i] and *(B) implies B[0], that is *(B+0)=*(B)=B[0].
#include <stdio.h>
int func(int *B){
*B = 5;
// if you want to modify ith index element in the array just do *(B+i)=<value>
}
int main(void){
int B[10] = {};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
main()
{
int *arr[5];
int i=31, j=5, k=19, l=71, m;
arr[0]=&i;
arr[1]=&j;
arr[2]=&k;
arr[3]=&l;
arr[4]=&m;
for(m=0; m<=4; m++)
{
printf("%d",*(arr[m]));
}
return 0;
}
Using the really excellent example from Greggo, I got this to work as a bubble sort with passing an array as a pointer and doing a simple -1 manipulation.
#include<stdio.h>
void sub_one(int (*arr)[7])
{
int i;
for(i=0;i<7;i++)
{
(*arr)[i] -= 1 ; // subtract 1 from each point
printf("%i\n", (*arr)[i]);
}
}
int main()
{
int a[]= { 180, 185, 190, 175, 200, 180, 181};
int pos, j, i;
int n=7;
int temp;
for (pos =0; pos < 7; pos ++){
printf("\nPosition=%i Value=%i", pos, a[pos]);
}
for(i=1;i<=n-1;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)) // while selected # less than a[j] and not j isn't 0
{
a[j+1]=a[j]; //moves element forward
j=j-1;
}
a[j+1]=temp; //insert element in proper place
}
printf("\nSorted list is as follows:\n");
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
printf("\nmedian = %d\n", a[3]);
sub_one(&a);
return 0;
}
I need to read up on how to encapsulate pointers because that threw me off.
The argument of func is accepting double-pointer variable.
Hope this helps...
#include <stdio.h>
int func(int **B){
}
int main(void){
int *B[10];
func(B);
return 0;
}
In the function declaration you have to type as
VOID FUN(INT *a[]);
/*HERE YOU CAN TAKE ANY FUNCTION RETURN TYPE HERE I CAN TAKE VOID AS THE FUNCTION RETURN TYPE FOR THE FUNCTION FUN*/
//IN THE FUNCTION HEADER WE CAN WRITE AS FOLLOWS
void fun(int *a[])
//in the function body we can use as
a[i]=var

Resources