Convert const void pointer to int pointer - c

compiler shows me that:
In function ‘int compare(const void*, const void*)’:
invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
That's my function:
int compare(void const *a, void const *b) {
int *a2 = (int*)a;
int *b2 = (int*)b;
int *uziv1=*((const int**)a2);
int *uziv2=*((const int**)b2);
if(abs(uziv1[0]) < abs(uziv2[0])) return -1;
if(abs(uziv1[0]) > abs(uziv2[0])) return 1;
if(abs(uziv1[1]) < abs(uziv2[1])) return -1;
if(abs(uziv1[1]) > abs(uziv2[1])) return 1;
return 0;
}
I need to convert the two pointers from void to int to read from the array they point to and compare the values. The function needs to have the given signature such that it can be used for qsort.

Converting from a const pointer to a normal pointer is not allowed, because this would break the guarantee given by const (nobody should be able to write to it).
However, as you only want to read from these pointers, it is possible (and recommended) to simply declare them as const. Then you even do not need any cast at all:
const int *uziv1 = a;
const int *uziv2 = b;

I finaly fix it with:
...
int const *uziv1=*(( int const **)a);
int const *uziv2=*(( int const **)b);
...

Related

C [-Wincompatible-pointer-types] how to cast

my code: https://godbolt.org/z/de7fbdjh7
code from source: https://stackoverflow.com/a/49072888/15603477
Almost exact the same.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int iValue;
int kValue;
char label[6];
} my_data;
int cmp_mydata_ivalue(my_data* item1 , my_data* item2 )
{
if(item1->iValue < item2->iValue) return -1;
if(item1->iValue > item2->iValue) return 1;
return 0;
}
int main(void){
my_data datalist[256] = {0};
{
int i;
for(i = 0;i<20;i++){
datalist[i].iValue = i+100;
datalist[i].kValue = i+1000;
sprintf(datalist[i].label,"%2.2d", i+10);
}
}
printf("new line\n");
{
my_data srchitem = {105,1018,"13"};
my_data *foundItem = (my_data*) bsearch(&srchitem, datalist,20, sizeof(my_data),cmp_mydata_ivalue);
bsearch_results(&srchitem, foundItem);
}
}
The same question asked many times. But I don't know how to cast it.
error code:
*callback1.c: In function ‘main’:
callback1.c:58:89: warning: passing argument 5 of ‘bsearch’ from incompatible pointer type [-Wincompatible-pointer-types]
58 | my_data *foundItem = (my_data*) bsearch(&srchitem, datalist,20, sizeof(my_data),cmp_mydata_ivalue);
| ^~~~~~~~~~~~~~~~~
| |
| int (*)(my_data *, my_data *) {aka int (*)(struct <anonymous> *, struct <anonymous> *)}*
One way to try to use gcc option to supress the error. Another way is somewhere I need to cast. But now i don't know how to cast.
Tutorial I found so far: https://www.tutorialspoint.com/c_standard_library/c_function_bsearch.htm
The comparison function must have the type
int ( const void *, const void * )
See the declaration of the function bsearch
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
So you should declare and define your function like
int cmp_mydata_ivalue( const void *a , const void *b )
{
const my_data *item1 = a;
const my_data *item2 = b;
if ( item1->iValue < item2->iValue) return -1;
if(item1->iValue > item2->iValue) return 1;
return 0;
}
Don't ever use workarounds to suppress errors/warnings from the compiler. You should carefully understand them and fix the code instead. If you chose to ignore them, you must be very conscious of what are the implications.
Having said that, the bsearch prototype is the following:
void* bsearch( const void *key, const void *ptr, size_t count, size_t size,
int (*comp)(const void*, const void*) );
meaning it expects the last parameter to be a function pointer to a function with the following signature:
int function(const void*, const void*);
What you are passing is a function of this kind
int cmp_mydata_ivalue(my_data* item1 , my_data* item2 )
Which is uncompatible, as C can't do any implicit cast. You must rewrite your function to something like this:
int cmp_mydata_ivalue( const void *cvp_item1 , const void *cvp_item2 )
{
const my_data *item1 = (const my_data *)cvp_item1;
const my_data *item2 = (const my_data *)cvp_item2;
}

C type won't be recognized properly

I have an error when I compile my C program.
I have this code :
#include <stdio.h>
#include <stdlib.h>
#define SET__SIZE 10
#define SET__BOUND ((void*) NULL)
struct set {
void *s[SET__SIZE];
int cursor;
int (*cmp)(const void*, const void*);
void * (*copy)(const void*);
void (*del)(void *);
};
int find(const void *s[], void *c, int (*cmp)(const void*, const void*))
{
int i = 0;
while (s[i]!=SET__BOUND && cmp(s[i],c)<0)
i++;
return i;
}
int set__find(const struct set *se, void *c)
{
return (se->cmp(se->s[find(se->s,c,se->cmp)],c)==0);
}
For some reason, gcc is raising a warning for the find call in set__find saying :
note: expected ‘const void **’ but argument is of type ‘void * const*’
I can't understand why he thinks the argument is a constant pointer (if I understood the error right)
As I tried, the note goes away, when I change the code to
struct set {
void *s[SET__SIZE];
int cursor;
int (*cmp)(const void*, const void*);
void * (*copy)(const void*);
void (*del)(void *);
};
int find(void * const s[], void *c, int (*cmp)(const void*, const void*))
{
int i = 0;
while (s[i]!=SET__BOUND && cmp(s[i],c)<0)
i++;
return i;
}
int set__find(const struct set *se, void *c)
{
return (se->cmp(se->s[find(se->s,c,se->cmp)],c)==0);
}
Explanation
In the answer... No point of writting it again.
why he thinks the argument is a constant pointer
struct set {
void *s[SET__SIZE];
The structure set contains the array s.
const struct set *se
se points to a constant structure set. Because the structure is constant, the memory for the structure is constant. The elements of the array s can't be modified, they are in constant memory.
find(se->s,
Arrays decay to the pointer to the first element. So imagine it's TYPE s[SET__SIZE] where TYPE is a void*. TYPE s[SET__SIZE] decays to a pointer TYPE *. But, it's constant, so it's const TYPE s[SET__SIZE]. So it decays to a const TYPE *. You can't modify it, it's a constant array. TYPE is a void* - you can dereference the element and modify it then, but you can't modify the pointer value itself.
TL;DR you want int find(void * const s[] as in the other answer.

warning: initialisation from incompatible pointer type

Hi all it's been sometime since I've touched C so I'm really rusty on it. I wrote a small program to create a matrix using two dynamic arrays. However, I'm getting this warning and I don't understand why? I guess I'm not quite sure about pointers to pointers. Can someone help me point out where my problem is? Thanks.
sm.c: In function ‘main’:
sm.c:11:13: warning: initialisation from incompatible pointer type [enabled by default]
sm.c: In function ‘makeMatrix’:
sm.c:27:3: warning: return from incompatible pointer type [enabled by default]
#include <stdio.h>
#include <stdlib.h>
typedef int (**intptr) ();
intptr makeMatrix(int n);
int main(int argc, char *argv[]) {
int n = 2;
int **A = makeMatrix(n);
if(A) {
printf("A\n");
}
else printf("ERROR");
}
intptr makeMatrix(int size) {
int **a = malloc(sizeof *a * size);
if (a)
{
for (int i = 0; i < size; i++)
{
a[i] = malloc(sizeof *a[i] * size);
}
}
return a;
}
You've got some problems here:
typedef int (**intptr) ();
intptr makeMatrix(int n);
...
int **A = makeMatrix(n);
The intptr typedef declares a pointer to a pointer to a function that takes an indeterminate number of arguments and returns an int. A is not an int.
You need to write:
int **makeMatrix(int n);
int **A = makeMatrix(n);
Using a typedef won't help much here.
typedef int **(*intptr)();
That declares a pointer to a function that returns a pointer to a pointer to an int. But writing
intptr makeMatrix(int n);
would declare that makeMatrix() returns a pointer to a function, not an int **.
Your typedef has an extra (), making it a zero argument function type. Remove that and you should be good.

How do I call an arbitrary C function passed to another function?

I'm writing a unit test framework (see SO for more details). Or view the code at GitHub.
Safer Code describes a way to pass functions of arbitrary types.
But how do I call such a function without knowing its types beforehand? Assume f needs no input, so f() should work on its own.
Let's say I want to populate an array using an arbitrary generator function.
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = gen(NULL);
}
return arr;
}
It should look something like this, but I get compiler errors:
gcc -o example example.c qc.c qc.h -lgc
In file included from example.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
In file included from qc.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
qc.c:23: error: conflicting types for ‘gen_array’
qc.h:21: error: previous declaration of ‘gen_array’ was here
qc.c: In function ‘gen_array’:
qc.c:29: warning: dereferencing ‘void *’ pointer
qc.c:29: error: too many arguments to function ‘gen’
qc.c:29: error: invalid use of void expression
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
make: *** [example] Error 1
After thinking about some more I realize your problem your above code would never work.
You are first calling trying to call a void function with no parameters with the parameter NULL. Next you would need your code to be more generic. I placed an example below of what I mean. Now using a global variable
#include <stdio.h>
#include <stdlib.h>
typedef void (*fp)(void);
void * GEN_ARRAY_TEMP;
int gen_int() {
return 67;
}
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = malloc(len * size);
void* arr_end = arr + len * size;
GEN_ARRAY_TEMP = arr;
while (GEN_ARRAY_TEMP <= arr_end) {
gen();
GEN_ARRAY_TEMP+=size;
}
return arr;
}
void make_int() {
(*(int*)GEN_ARRAY_TEMP) = 9;
}
int main() {
int i;
int * gen_int_array = (int*) gen_array(make_int, sizeof(int));
for(i=0;i<67;i++) {
printf("%d\n",gen_int_array[i]);
}
}
That page suggests you make the function pointer take a void*. So in order for your code to compile, you must pass it a void pointer:
typedef void* (*fp)(void*);
doit(fp f) {
f(NULL);
}
And just make sure that the function that you're calling simply ignores the parameter.
Generally speaking, these generic function pointers are used for starting threads. The void pointer is simply a pointer to a struct that holds the actual parameters.
What would you need to do is wrap your function in a void function like so
#include <stdio.h>
typedef void (*fp)(void);
int sum(int x,int y) {return x+y;}
void doit(fp f) {
f();
}
void func() {
printf("Hello %d\n",sum(1,2));
}
int main() {
doit(func);
}
You have two problems:
First, qc.h is missing a <stdlib.h> include. This is needed for use of size_t.
Second, in gen_array, you create a void *arr, then try to dereference it as an array (arr[i]). Since the compiler doesn't know the size of your array elements, it cannot fill the array. You must treat it as a char *, offset by arr + size * i, and pass it into gen rather than taking a return (returns also need to know the structure size):
// ...
char *arr = GC_MALLOC(len * size);
for (int i = 0; i < len; i++) {
gen(arr + i * size, NULL);
}
return arr;
This will of course require changing the fp type definition.
For the case where your pointer to a function 'fp' is of type which takes no argument and returns void, in which case you should declare it as :
typedef void (*fp)();
In the above case the call should be :
(*gen)();
If your pointer to the function 'fp' is of type which takes 'void *' as argument and returns void, in which case you should declare it as :
typedef void (*fp)(void *);
In the above case the call should be :
(*gen)(NULL);
or any other pointer variable you might want to pass.
As far as your example goes try this :
typedef void * (*fp)(void *);
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = (*gen)(NULL);
}
return arr;
}

Warning when using qsort in C

I wrote my comparison function
int cmp(const int * a,const int * b)
{
if (*a==*b)
return 0;
else
if (*a < *b)
return -1;
else
return 1;
}
and i have my declaration
int cmp (const int * value1,const int * value2);
and I'm calling qsort in my program like so
qsort(currentCases,round,sizeof(int),cmp);
when i compile it I get the following warning
warning: passing argument 4 of ‘qsort’ from incompatible pointer type
/usr/include/stdlib.h:710: note: expected ‘__compar_fn_t’ but argument is of type ‘int
(*)(const int *, const int *)’
The program works just fine so my only concern is why it doesn't like the way im using that?
The cmp function's prototype must be
int cmp(const void* a, const void* b);
You can either cast it in the invocation of qsort (not recommended):
qsort(currentCases, round, sizeof(int), (int(*)(const void*,const void*))cmp);
or casts the void-pointers to int-pointers in cmp (the standard approach):
int cmp(const void* pa, const void* pb) {
int a = *(const int*)pa;
int b = *(const int*)pb;
...
According to the man page, a __compar_fn_t is defined as: typedef int(*) __compar_fn_t (const void *, const void *)
Your cmp specifies int* parameters. It doesn't like that, but is only listed as a warning.

Resources