C Passing double pointer from function - c

I am working on a non homework question that I just can't solve no matter what I try.
The problem is one from Project Euler that involves solving for even Fibonacci numbers and summing them together, I chose this one as a chance to learn more about functions, pointers, and working with large numbers that would be best served by not copying their value but instead passing a memory address.
I currently have the following:
/*Second attempt at fibo 4mil
problem.*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
//MAX is 20 for testing reasons
//Actual value is MAX 0X3D0900
#define MAX 20
//Function will accept even fibo numbers
//then sum them together for output later
void evenCount (double* evenPoint);
int main(void){
double firstVar = 0;
double secondVar = 1;
double thirdVar;
double modVar = 2;
double sumVar;
double count;
for(count = 0; count < MAX; count++){
thirdVar = firstVar + secondVar;
secondVar = firstVar;
firstVar = thirdVar;
if(fmod(firstVar, modVar) == 0){
evenCount(&firstVar);
}
printf("Currently: %.2f\n", firstVar);
}
sumVar = &evenCount();
printf("Final even sum is: %f\n", sumVar);
return 0;
}
void evenCount (double* evenPoint){
double tempOne, tempTwo, tempThree;
tempOne = *evenPoint;
tempThree = tempOne + tempTwo;
tempTwo = tempOne;
tempOne = tempThree;
evenPoint = &tempOne;
}
I can't tell if the data from main() is being properly passed to the evenCount function for them to be summed and have it's value updated to be printed at the end of main().
My questions are:
Do I need a second double pointer in evenCount to pass the final value or can I just reference one value updating it as it loops through?
Does main() need a pointer so that pointer can reference evenCount pointer?
I would really appreciate any help because I have bought a Safari online subscription, have the "C A Reference Manual" sitting next to me but I just can't figure this out. Plus i read over this question and it kind of answered my question, but the person is using multiple function prototypes.
too few arguments to function and can't be used as a function---- beginning C
Thanks to anybody that looks

I am not completely clear about what the evenCount() function is supposed to do.
Fact is that you are calling it the wrong way - sumVar = &evenCount(); is even twice wrong, as it is missing an argument and the & doesn't make sense - and that it doesn't do what you probably want.
Let's have a look:
void evenCount (double* evenPoint){
double tempOne, tempTwo, tempThree;
Here you define three auto variables, but they haven't got a value yet.
tempOne = *evenPoint;
tempThree = tempOne + tempTwo;
What do you expect to be tempTwo here?
tempTwo = tempOne;
tempOne = tempThree;
evenPoint = &tempOne;
You might mean *evenPoint = tempOne here, but I am not sure.
}
I suppose you want a way to make a "step" in terms of Fibonacci numbers. So let's look:
In order to create the "next" Fib number, you need the two previous ones and add them together. So a "step" could be done in a function like
void fibStep(double * curr, double *prev) {
double new = *curr + *prev;
*prev = *curr;
*curr = new;
}
and then
int main(void){
double firstVar = 0;
double secondVar = 1;
double sumVar = 0;
int count; // no need to have this as a double...
for(count = 0; count < MAX; count++){
fibStep(&secondVar, &firstVar);
if(fmod(secondVar, 2) == 0){
sumVar += secondVar);
}
printf("Currently: %.2f\n", secondVar);
}
printf("Final even sum is: %f\n", sumVar);
return 0;
}

I'm not quite sure what evenCount is meant to do as it is. Edit: see below.
From your description of the problem, it seems like you could just do:
int isEven(unsigned int number)
{
return !(number%2);
}
int main()
{
unsigned int first = 1, second = 1, next, sum = 0;
//we already have the first two numbers so start at 2
for(count = 2; count < MAX; count++)
{
next = first+second;
first = second;
second = next;
//we know the starting values are odd (1 & 1) and won't need to be summed so we can test the new value -
if (isEven(second)) //if even (no remainder when dividing by 2)
{ sum+=first;}
}
printf("Final even sum is: %f\n", sum);
}
Note, there is no need for double here (yet). The sum (at n=20) is still far too low to exceed what int can store. (although at this point it is growing quickly)
As for your actual questions:
note: when you don't need a pointer, it is recommended that you don't use one, as all you are going to do is make the code more complex than needed
Do I need a second double pointer in evenCount to pass the final value?
If the function is meant to keep track of the sum, then I'd do it like this:
unsigned int evenSum(unsigned int num = 0)
{
static unsigned int sum = 0; //initialised on first use of function. Value is retained between function calls.
//we test for even here - no longer need to test in calling code
// - making the algorithm simpler
if (isEven(num))
sum += num;
return sum;
}
which can then be called like this:
//adding values:
evenSum( new_value );
//retrieving sum
sum = evenSum();
//or do both:
sum = evenSum( new_value );
If you wanted to store the sum 'locally' though (i.e. as a variable in main, but modify it in the evenSum() function), then yes, you would then need to pass it into the funtion too as a pointer:
void evenSum(unsigned int num, unsigned int * sum)
{
if (isEven(num))
*sum += num;
}
It would be called like this:
sum = 0;
num = 56;
evenSum(num, &sum); //sum is now sum+num
As you pass the address of sum in, when the function de-references it, it modifies the value and not a copy. The number passed in does not need to be passed in as a pointer as it is a (forgetting correct word here, but it means 'basic') type, and passing it by value is actually slightly more efficient as at runtime it can just be loaded into a register, and doesn't rely on memory lookup. Plus, it is easier to read.
Does main() need a pointer so that pointer can reference evenCount pointer?
To be honest, I'm not 100% sure what you are asking here.
If you are asking:
Do I need to store a pointer to the sum in main() to pass into the evenSum() function?
then no.
You can pass a pointer to a 'thing' using the "address of" operator &. I've used it above in the second calling example in the above answer:
unsigned int * sum_pointer = ∑// <--- not needed
evenSum(num, &sum); //sum is now sum+num
^
This passes a pointer to sum
Edit: looking at your code again, is evenCount meant to find the next fibonachi number?
If so, you could do:
void next_fib(unsigned int *previous, unsigned int *current)
{
unsigned int next = *previous+*current;
*previous = *current;
*current = next;
}
And you would call this like so:
unsigned int val1 = 1, val2 = 1;
next_fib(&val1, &val2); //val2 is now the 3rd fib. #
next_fib(&val1, &val2); //val2 is now the 4th fib. #
To add this to my code from above, the program becomes:
int isEven(double number)
{
return !(number%2);
}
unsigned int evenSum(double num = 0)
{
static double sum = 0;
//we test for even here - no longer need to test in calling code
// - making the algorithm simpler
if (isEven(num))
sum += num;
return sum;
}
void next_fib(unsigned int *previous, unsigned int *current)
{
unsigned int next = *previous+*current;
*previous = *current;
*current = next;
}
int main()
{
unsigned int first = 1, second = 1;
//we already have the first two numbers so start at 2
for(count = 2; count < MAX; count++)
{
next_fib(&first, &second);
evenSum(second);
}
printf("Final even sum is: %f\n", evenSum());
}
Edit 2:
After reading your edit and some of your comments, and then taking a look at the actual task, you have interpreted the question incorrectly.
The question asks for the sum of all even numbers in the fibbonachi sequence, where the number is less than 4x106. This is thankfully easier and quicker to do than the sum of all the even Fibonacci numbers up to the 4x106th.
Obviously, we need to change the algorithm. Luckily, we split the main bits into functions already, so it's pretty simple, mainly just a change in the loops, though I made a couple more changes too:
bool isEven(unsigned long number)
{
return !(number%2);
}
void next_even_fib(unsigned long *previous, unsigned long *current)
{
do
{
unsigned int next = *previous+*current;
*previous = *current;
*current = next;
} while (!isEven( *current));
//we could just do 3 passes here without needing the isEven() function
//as the Fibonacci sequence is always O,O,E,O,O,E...
//but this is a more general form
}
int main()
{
//as there is less constraint on knowing which term we are on, we can skip straight to the first even number.
unsigned long first = 1, second = 2;
unsigned long sum = 0;
do
{
//with the sum calculation first, we can break out of the loop before the sum
//we've changed the algorithm so when we get here, second is always even
sum += second;
next_even_fib(&first, &second);
} while (second < 4000000);
printf("Final even sum is: %d\n", sum);
}
Note that I changed the types to unsigned long. This is still an integer value, but one that is guaranteed to be long ( :-P ) enough to store the numbers we need.

Passing of the value is correct but you can't do evenPoint = &tempOne; to return a value from the function. There are two problems in doing that: first is that C supports only pass by value, so when you pass a pointer you are in fact creating a copy of the pointer for the callee. Any modification of the data pointed will be visible to the caller but not modifications to the pointer argument itself. When you modify the pointer argument you are in fact modifying a stack variable that the caller has no access to.
What's the difference between passing by reference vs. passing by value?
You could change your code in the following way:
void evenCount (double** evenPoint){
double tempOne, tempTwo, tempThree;
tempOne = **evenPoint;
tempThree = tempOne + tempTwo;
tempTwo = tempOne;
tempOne = tempThree;
*evenPoint = &tempOne;
}
But that would mean that *evenPoint points to a variable allocated on the stack, precisely on the frame of evenCount. When evenCount returns the frame get popped out of the stack. Accessing that variable after it is outside the stack will cause undefined behavior.
Consider the following example where you call another function A() after evenCount before using evenPoint. A() function frame would be placed in memory at the same location of where evenCount frame was and its local variables might overwrite the value of evenPoint. When you subsequently read evenPoint you will find its value changed.
C++ Returning reference to local variable
Finally, you read the variable tempTwo which is an uninitialized automatic variable so you'll end up reading garbage.

Related

How to use qsort for structure members?

I am still learning about C programming, and I am having a bit of an issue with my program.
So my structure is declare in q.h file
#define MAXIMUM_LENGTH 80
struct Tsunami {
unsigned int day;
unsigned int month;
unsigned int year;
unsigned fatalities;
double height;
char location[MAXIMUM_LENGTH];
};
and the function that uses qsort is :
double get_median_height(const struct Tsunami* begin, size_t count)
{
double median = 0;
double compare1,compare2;
struct Tsunami* store = (struct Tsunami*) malloc (sizeof(struct Tsunami) * count);
for (int i = 0; i < (int)count; i++)
{
store[i].month = begin[i].month;
store[i].day = begin[i].day;
store[i].year = begin[i].year;
store[i].fatalities = begin[i].fatalities;
store[i].height = begin[i].height;
strcpy(store[i].location, begin[i].location);
}
qsort(store, count, sizeof(Tsunami), compare_events);
if(count % 2 == 0)
{
printf("%ld",count);
compare1 = store[(count/2)].height;
printf("%lf",compare1);
compare2 = store[(count/2) +1].height;
printf("%lf",compare2);
median = (compare1 + compare2)/2;
}
else
{
median = store[(count/2)].height;
}
free(store);
return median;
}
My compare_events code is
int compare_events(const void* first, const void* second)
{
struct Tsunami* first = (struct Tsunami*)first;
struct Tsunami* second = (struct Tsunami*)second;
return (second->height - first->height);
}
For some reason, it does not help me sort out the value of store.height from smallest to largest. Can someone explain to me why? and how should I use the qsort instead?
Your comparison function:
Is backwards. It's supposed to return a number less than zero if first < second, but yours does the opposite. So intuitively it should be return first->height - second->height. However...
As "chux - Reinstate Monica" alluded to in comments, your heights are of type double but the comparison function must return int. So your function implicitly converts their difference to an int, but this conversion always rounds toward zero. Thus any two heights that differ by less than 1 will have a difference less than 1, which will be rounded to zero and qsort will think the two Tsunamis are of equal height, and may put them in the array in any order.
What you really want is something like sign(first->height - second->height). Unfortunately C has no standard sign function, but you can find many possible implementations at Is there a standard sign function (signum, sgn) in C/C++?. (This will also fix another bug, which is that your function will not correctly compare heights whose difference doesn't fit in an int.)

How is plus-equals acting on this array of structs?

I was reading over some of the source code behind pngquant (here)
I got confused when I saw plus-equals seemingly assigning a new value to an array of structs (base += r in the code snippet below):
static void hist_item_sort_range(hist_item base[], unsigned int len, unsigned int sort_start)
{
for(;;) {
const unsigned int l = qsort_partition(base, len), r = l+1;
if (l > 0 && sort_start < l) {
len = l;
}
else if (r < len && sort_start > r) {
base += r; len -= r; sort_start -= r;
}
else break;
}
}
The hist_item definition is given as:
typedef struct {
f_pixel acolor;
float adjusted_weight, // perceptual weight changed to tweak how mediancut selects colors
perceptual_weight; // number of pixels weighted by importance of different areas of the picture
float color_weight; // these two change every time histogram subset is sorted
union {
unsigned int sort_value;
unsigned char likely_colormap_index;
} tmp;
} hist_item;
I apologize ahead of time, because I'm sure to those in the know this must be a really dumb question, but how is plus-equals operating on base, which appears to be an array of structs, and some integer r? It seems to me that this operation should be undefined for the combination of those two types.
I haven't had to write C for almost ten years, and I'm admittedly pretty rusty; however, searching for about thirty minutes only turned up answers to the wrong questions, and any help is appreciated. Thanks!
As explained in What is array decaying?
static void hist_item_sort_range(hist_item base[], unsigned int len, unsigned int sort_start)
becomes
static void hist_item_sort_range(hist_item* base, unsigned int len, unsigned int sort_start)
Where base is a pointer to the first element of the array. Therefore base += r; performs simple pointer arithmetic, i.e.: modifies the pointer to point to an offset of r elements from the start of the array.
Due to the += the original pointer is modified, so any access happens with offset from the now pointed to element.
To use the example from the comment:
After base += 1; accessing the "first" element via &base[0]; yields a pointer to the same element as &base[1]; before the increment

How to access an array within a structure using only pointer arithmetic

Is it possible to do the same thing as I did below, but without using [] or ->.
I don't understand why .*(points + 2) doesn't work. Shouldn't this replace array?
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int points[2];
}_student;
int foo(_student *stud);
int main()
{
int second;
_student students[2];
students[1].points[1] = 100;
second = foo(students);
printf("%d", second);
return 0;
}
int foo(_student *stud) // returns 3rd member of the array within a struct
{
int second;
second = (*(stud+1)).points[1]; // Works
//second = (*(stud+1)).*(points+1); ----> Does not work!
return second;
}
The result should be 100.
You don't say what is failing in your code, but whatever it is, it's because of buffer overflow.
Here
_student students[2];
students[2].points[2] = 100;
you can't access students[2] because it's the third element, and your array has only two, accessing the third element invokes undefined behavior, and of course the same goes for points.
In c, an array index starts at 0, instead of 1, hence the second element would be
_student students[2];
students[1].points[1] = 100;
Also don't use that kind of identifier for a type name, it's quite confusing, and generally it's better to make it clear when something is a struct, like in this case.
I would recommend the following
struct student {
int points[2];
};
struct student students[2];
students[1].points[1] = 100;
Edit: Since the question was edited now the above content seems not logical or incorrect, the actual problem is that this syntax
second = (*(stud+1)).*(points+1); /* ----> Does not work for sure ! */
is invalid, the obvious way is
second = *((*(stud + 1)).points + 1); /* ----> Does work! */
or even
second = *((stud + 1)->points + 1); /* ----> Does work! */
I don't understand why .*(points + 2) doesn't work. Shouldn't this replace array?
A good question would be, Why do you think it should work?

Calculate the sum of two numbers using thread

I have this little program I wrote to read two numbers from a user and calculate their sum using a thread function, which is also responsible for displaying the result on the screen.
int global[2];
void *sum_thread(void *arg)
{
int *args_array;
args_array = *(int**)arg;
int n1,n2,sum;
n1=args_array[0];
n2=args_array[1];
sum = n1+n2;
printf("N1 + N2 = %d\n",sum);
return NULL;
}
int main()
{
printf("First number: ");
scanf("%d",&global[0]);
printf("Second number: ");
scanf("%d",&global[1]);
pthread_t tid_sum;
pthread_create(&tid_sum,NULL,sum_thread,(void*)&global);
pthread_join(tid_sum,NULL);
return 0;
}
However, when I run the code, it does not work properly due to a segmentation fault. I suppose I am trying to access/use unallocated memory. Should I allocate it with malloc or is there other things I am doing wrong?
The name of the array, global points to the base address of the array. You can simply pass that and use the same inside your thread function.
However, just to mention a logical point, if you're passing global as a parameter to sum_thread() function, it need not be a global.
In your code, change
pthread_create(&tid_sum,NULL,sum_thread,(void*)&global);
to
pthread_create(&tid_sum,NULL,sum_thread,global);
Then, in sum_thread() function
args_array = *(int**)arg;
to
args_array = arg;
You pass (void*)&global as the thread start function's argument. The type of &global is (*)int[2] -- pointer to array of two int. That is different from and incompatible with int **, which is a pointer to a pointer to int. Arrays are not pointers.
#SouravGhosh already offered a solution that gets the typing correct, and should work just fine. I observe, however, that in this particular case it's a bit silly to pass a pointer to the global array, because the thread could instead just read the array directly:
void *sum_thread(void *arg)
{
int n1,n2,sum;
n1=global[0];
n2=global[1];
sum = n1+n2;
printf("N1 + N2 = %d\n",sum);
return NULL;
}

C: When is a variable or value considered used?

I am cleaning up some code from a Coverity issue and have a situation where a pointer local to a function is used earlier on is a function for comparison, then later on it is assigned to point else where but it is never de-referenced or used to assign something to its value. Coverity is saying that it is an unused pointer value - so I am thinking to cast it to a void to indicate the pointer is not used after that point. I am wondering when is a value or variable considered used in a program? Here is a code sample explaining my situation:
In the sample below Coverity would flag the fltr_ptr as not being used after its two assignments at the end of the sample
int initialise (void)
{
// pointer first decalred and defined
FILTER_PTR fltr_ptr = NULL;
// pointer given valid value
fltr_ptr = global_val->filter_group[index];
// second use of fltr_ptr
if ( TRUE == fltr_ptr -> being_used)
{
// first use of fltr_ptr
if ( TRUE != close_filter ( fltr_ptr -> Filter)
{
// print error
}
// do more code
// fltr_ptr assigned first time , value not used should it be (void)fltr_ptr?
fltr_ptr = Free_Memory (fltr_ptr, sizeof(FILTER_PTR));
}
else
{
return 1;
}
for ( number of iterations )
{
// fltr_ptr assigned again but value not used should it be (void)fltr_ptr?
fltr_ptr = global_val->filter_group[index];
}
return 0;
}
Coverity points to you that you assign to fltr_ptr in the last for loop but you do nothing with this value. Why assign at all? Casting to void could possibly fix the warning, but the first thing to fix should be either to use the pointer somehow, or stop assigning to it.
To answer the title question, a variable is considered unused when "it is initialised or assigned to and then disposed of without being read."
int main()
{
int i;
int j = 1; // both i and j are unused at this point
int i = j * 2; // j is now 'used', the new value of i is unused
printf("%d",j);//j is used again
} // i goes out of scope without being used.
note that the definition isn't also "if it is assigned to without being read" as this would indicate that there was a problem with the following:
unsigned int find_max_index(int a[], int size)
{
unsigned int i;
unsigned int maxval = 0;
unsigned int maxindex = 0;
for (i = 0; i< size; i++){
if (a[i]>maxval){
maxval = a[i];
maxindex = i;
}
}
return maxindex;
}
As in this code maxindex can be assigned to multiple times without being read.
Looking back at my original example, we can eliminate i without any change to the program. This reduces the complexity of the program, removes redundant operations (though the compiler should do this when optimising too) and reduces the chance of programmer error in the future:
//FUNCTIONALLY THE SAME AND SIMPLER
int main()
{
int j = 1; // j is unused at this point
printf("%d",j);// j is used
}
In the same way, you can remove this entire loop:
for ( number of iterations )
{
// fltr_ptr assigned again but value not used should it be (void)fltr_ptr?
fltr_ptr = global_val->filter_group[index];
}
(You remove the assignment and get an empty loop. as this is a long nop, it can also be removed)

Resources