I saw something in someones code that I don't understand. What does it say in the return statement?
static cell_ptr UD_self(cell_ptr c) { return c->U = c->D = c; }
here is defined:
struct cell_s;
typedef struct cell_s *cell_ptr;
struct cell_s {
cell_ptr U, D, L, R;
int n;
union {
cell_ptr c;
int s;
};
};
It's just a shorthand way of writing this:
{
c->D = c;
c->U = c->D;
return c->U;
}
The statement return c->U = c->D = c; works because the assignment operator = returns the value it has just assigned. This value is then used in the next assignment. It associates from right to left, so it means return (c->U = (c->D = c));
Related
Say I have these two functions and a definition of an array of these two functions:
int flag;
int add(int a, int b){
return a+b;
}
int multiply(int a, int b){
return a*b;
}
typedef int(*f)(int, int);
f func_array[2] = {&add, &multiply};
Now, there is a specific place in my code that I want to call these two functions depending on my flag state with the same arguments each time.
For example:
int var;
if(flag == 0)
{
var = func_array[flag](1,1);
}
else{
var = func_array[flag](2,2);
}
Is there a way to define it inside the array itself? Somwhow defining the array like this and just call the function:
f func_array[2] = {&add(1,1), &multiply(2,2)};
int var = func_array[flag]();
Is this a valid way? Is there any more elegant way to do it?
You can define a set of arrays for each parameter:
#define ARR_SIZE 2
typedef int(*f)(int, int);
f func_array[ARR_SIZE] = {&add, &multiply};
int param1_array[ARR_SIZE] = { 1, 2};
int param2_array[ARR_SIZE] = { 1, 2};
The call would become
if(flag < ARR_SIZE)
{
int var = func_array[flag](param1_array[flag], param2_array[flag]);
}
I just added a check on the array size.
With a macro
#define flag_call(flag) \
func_array[flag](param1_array[flag], param2_array[flag])
you could simplify it even more
if(flag < ARR_SIZE)
{
flag_call(flag);
}
Not sure what the point is but you can do this:
int add11(void){ return add(1,1); }
int multiply22(void){ return multiply(2,2); }
/*skipped the new typedef*/
int (*func_array2[2])(void) = {&add11,&multiply22};
https://godbolt.org/z/ejMn4n
The wrappers could even be inlinable if you make the array static or auto.
You can use a struct to bundle them together:
typedef int(*f)(int, int);
struct func_and_args {
f func;
int a;
int b;
}
...
struct func_and_args arr[] = {{&add,1,1},{&multiply,2,2}};
int var = arr[flag].func(arr[flag].a,arr[flag].b);
void f(int a, char b, char* c) {
if(..) {
...
f(a,b,c); //recursive
}
...
}
void g(int a, double b, char* c, int d) {
if(..) {
...
g(a,b,c,d); //recursive
}
...
}
I want to make a separate function because I use the code within the if statement several times. But this function have to have a function as a parameter becuase I use recursive method. I know that we can use function as a parameters, but in the f function there are 3 parameters, in the g function have 4 parameters.
The code in the if statement in f is the same as the code in the if of g. Except for the function call in that code?
Simply I have no idea how to solve this issue.
You can use union to pack the variable number of arguments, as shown in sample code below.
It may be unusual to use union like this, but it works.
#include<stdio.h>
union u {
struct { int a; char b; char* c; } f;
struct { int a; double b; char* c; int d; } g;
};
void func_u_f (union u* ua) {
printf(" f = {a: %d, b: %c, c:%s}\n", ua->f.a, ua->f.b, ua->f.c);
ua->f.a++;
}
void func_u_g (union u* ua) {
printf(" g = {a: %d, b: %e, c:%s, d:%d}\n",
ua->g.a, ua->g.b, ua->g.c, ua->g.d);
ua->g.a++; ua->g.b *= 2.0; ua->g.d++;
}
void r (int i, void (*func) (union u*), union u* ua) {
if (i < 3) { /* or whatever conditions to terminate recursion */
printf ("Recursion %d\n", i);
func(ua);
r (++i, func, ua);
} else {
printf ("Exit recursion at %d\n", i);
return;
}
}
int main () {
union u u1, u2;
/* f */
u1.f.a = 10; u1.f.b = 'X'; u1.f.c = "I am u.f.";
r(0, &func_u_f, &u1);
/* g */
u2.g.a = 10; u2.g.b = .4e-6; u2.g.c = "I am u.g."; u2.g.d = 98;
r(-2, &func_u_g, &u2);
return 0;
}
I am proposing you an easy fix that doesn't work in general because it involves the use of a sentinel value.
Let's say that the the variable d that you pass to g is always positive. Than you can choose -1 as sentinel value.
You always pass four parameters to the function myIf and then check whether d is -1. If it is, then you call f with three parameters, otherwise you call g.
int main() {
myIf(a, b, c, d);
return 0;
}
void myIf(int a, int b, char *c, int d)
{
if( d == -1 ) {
f(a, b, c);
}
else {
g(a, b, c, d);
}
}
I'm not sure exactly what you're trying to do. But if you're worried about code duplication in the if statements, you can refactor that our to another function:
if (isCondition()) ...
bool isCondition() { return ... }
What is bool (*comparator)(void *, void *)?
I'm trying to use this function from a library, but I don't understand its signature.
The function seems to be expecting some kind of criteria to sort the list (as ASC or DESC in SQL, I think), as a higher order function.
void list_sort(t_list *self, bool (*comparator)(void *, void *)) {
int unsorted_elements = self->elements_count;
if(unsorted_elements < 2) {
return;
}
t_link_element *aux = NULL;
bool sorted = true;
do {
t_link_element *previous_element = self->head, *cursor = previous_element->next;
sorted = true;
int index = 0, last_changed = unsorted_elements;
while(index < unsorted_elements && cursor != NULL) {
if(!comparator(previous_element->data, cursor->data)) {
aux = cursor->data;
cursor->data = previous_element->data;
previous_element->data = aux;
last_changed = index;
sorted = false;
}
previous_element = cursor;
cursor = cursor->next;
index++;
}
unsorted_elements = last_changed;
} while(!sorted);
}
The last definition of the function was in commons/collections/list.h.
I can't figure how to use this function properly after many attempts.
#include <stdio.h>
#include <stdlib.h>
#include <commons/collections/list.h>
/*I added this function thanks to the help of the community,
*and now it works, the list is printed backwards now.*/
bool comparator(void * a, void * b) {
return (int*) a > (int*) b;
}
int main()
{
t_list *list = list_create();
int add[] = {4, 55, 9, 7, 17};
list_add(list, (void*) &add[0]);
list_add(list, (void*) &add[1]);
list_add(list, (void*) &add[2]);
list_add(list, (void*) &add[3]);
list_add(list, (void*) &add[4]);
int size = list_size(list);
int j = 0 ;
while( j++ < 2)
{
for ( int i = 0 ; i < size; i++)
{
int* element = (int*) list_get(list, i);
printf("Found %d\n", *element);
}
//I edited this line, now the second parameter is comparator
list_sort(list, comparator);
}
list_destroy(list);
}
The main() function prints
Found 4 Found 55 Found 9 Found 7 Found 17
Found 17 Found 7 Found 9 Found 55 Found 4
EDIT:
I created the function comparator that actually allows me to run the code
After printing the result I showed before, it prints the same list but backwards.
Thanks everyone who's been nice and helped me fixed this, I still don't know how to print the sorted list. Sorry if my question is useless and/or violates some guideline, I wouldn't ask it this way if I knew it did.
Looking at the code in your last edit, the function is plain wrong. (int*) a > (int*) b compares pointer addresses, not values. If you intend to return true if a is greater than b, then it should be:
bool is_greater (void * a, void * b) {
return *(int*) a > *(int*) b;
}
More readably written as:
bool is_greater (void* a, void* b)
{
const int* ia = a;
const int* ib = b;
return *ia > *ib;
}
The function pointer type used by that API has some code smell, the parameters should have been declared as const void* so that the code can be used on read-only data too, but I guess you can't change that part.
In C++ we would have a predicate - an operator which returns true if the lhs < rhs
So your C function looks like it is following that pattern.
bool myLessInt(void * lhs, void * rhs)
{
// assume input parameters lhs and rhs are pointers into the data.
int intLhs = *((int*)lhs);
int intRhs = *((int*)rhs);
if( intLhs < intRhs ) return true; // lhs was less than rhs
return false; // rhs == or is less than lhs
}
I would look for a function like the one above to solve your problem.
I am struggling with using unions. Why am I unable to pass the function pointer to where the union would be? Any help would be greatly appreciated.
Edit: removed a typedef
#include <stdio.h>
union U {
int(*fnPtr)(int);
int i;
};
enum E {
OPTION_0 = 0,
OPTION_1 = 1
};
int multiply_by_two (int x) {
return 2 * x;
}
int f (int x, enum E e, union U u) {
switch (e) {
case OPTION_0:
/* Return the sum */
return x + u.i;
case OPTION_1:
/* Return 2 * x */
return u.fnPtr (x);
}
}
int main (void) {
int a;
scanf ("%d", &a);
int b = f (a, OPTION_1, &multiply_by_two);
printf ("%d\n", b);
return 0;
}
First, this definition is not valid:
union U {
typedef int(*fnPtr)(int);
int i;
};
You can't have a typedef inside of a struct or union. Removing the typedef will give you a proper definition:
union U {
int(*fnPtr)(int);
int i;
};
The second problem is here:
int b = f (a, OPTION_1, &multiply_by_two);
The function f expects a union U, but you're passing it a int (*)(int). Those types are not compatible. Just because the union has a member of that type doesn't mean you can use that type wherever you would use the union. You need to create a union, set the proper field, then pass that to the function.
union U u;
u.fnPtr = multiply_by_two;
int b = f (a, OPTION_1, u);
In main function, try this:
int main()
{
...
union U myUnion;
myUnion.fnPtr = &multiply_by_two;
int b = f (a, OPTION_1, myUnion);
...
}
And also, the union definition is not correct, you need to remove typedef.
Just to add to other answers: this is usually called a variant data type, and it makes sense to keep the type enum in a struct, along with the union, since you will be passing it around all the time anyway.
So I would recommend placing both in a struct:
enum var_type
{
VAR_INT = 0,
VAR_FUNC = 1
};
struct variant
{
// contains the type of the stored value
enum var_type type;
// contains the actual value
union {
int(*fnPtr)(int);
int i;
};
};
And then you can have separate functions for creating each subtype, for simpler instantiation:
// wrap the int value in the variant struct
struct variant variant_create_int(int i)
{
return (struct variant){ .type = VAR_INT, .i = i };
}
// wrap the functino pointer in the variant struct
struct variant variant_create_func(int(*fnPtr)(int))
{
return (struct variant){ .type = VAR_FUNC, .fnPtr = fnPtr };
}
Meaning your main would do something like:
// create variant of type 'VAR_FUNC'
struct variant var = variant_create_func(&multiply_by_two);
and just pass the var struct forward.
The Second Param of qsort
Now I want to sort a set of points by x.Following is my code:
typedef struct {
int x;
int y;
} point;
int cmpfunc( const void * a, const void * b){
point *point1 = (point *)(a);
point *point2 = (point *)(b);
if(point1->x < point2->x){
return -1;
}
return 0;
}
int main(){
point *points = (point *)malloc(sizeof(point)*3);
points[0].x = 1;
points[0].y = 2;
points[1].x = 0;
points[1].y = 4;
points[2].x = 4;
points[2].y = 3;
qsort(points,2,(sizeof(points[0])),cmpfunc);
int i=0;
while (i<3){
printf("x=%d",points[i].x);
printf("y=%d\n",points[i].y);
i++;
}
return 0;
}
Please notice qsort(points,2,(sizeof(points[0])),cmpfunc);
The result is correct when I pass the second param value 2 not 3.What's wrong with my code?
To sort on the x axis, you need something like:
static void cmpfunc(const void *a, const void *b)
{
const point *pa = a, *pb = b;
return pa->x < pb->x ? -1 : pa->x > pb->x;
}
It must return less than, equal to, or greater than zero. See the manual page for more.
Oh, and you really shouldn't "drop const" like that, for no reason, and of course you never need to cast from void * to a pointer to struct like we have here. Keep it simple, and learn these things so you don't feel a need to "throw in a cast for good measure".