warning: initialisation from incompatible pointer type - c

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.

Related

Setting array of pointers

i'm doing a small exercise to load an array of pointers (double pointer) to a struct. I have the following definition in the header file:
#include <stdio.h>
#define LEN (5)
typedef struct sample_s {
int num;
char *name;
}sample_t;
typedef struct new_sample_s {
char *string;
sample_t **sample_arr;
}new_sample_t;
sample_t table[LEN] = {
{0, "eel"},
{1, "salmon"},
{2, "cod"},
{3, "tuna"},
{4, "catfish"}
};
and using the definitions int this .c file:
#include "test.h"
void print_new_sample_array(sample_t **sample_arr) {
int len = sizeof(table)/sizeof(new_sample_t);
for(int i = 0; i < len; i++){
printf("The array element is: %s\n", sample_arr[i]->name);
}
}
int main() {
new_sample_t new_sample;
new_sample.sample_arr = table;
print_new_sample_array(new_sample.sample_arr);
return 0;
}
I have two questions:
First I'm not sure how to correctly load the table to the new_sample.sample_arr
Error message here:
test.c: In function ‘main’:
test.c:13:27: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
new_sample.sample_arr = table;
^
Second, I'm not sure how I can refer to the properties of each element in the sample_arr. For example, when I do the following, the program errored out:
for(int i = 0; i < LEN; i++){
printf("This is the elem in the array: %s", new_sample[i]->name);
}
I'm trying to learn more about the double pointer concept and why I did it wrong. I would really appreciate the answer keeps the sample_arr as double pointer
Thank you!
In this assignment statement
new_sample.sample_arr = table;
the right operand (after implicit conversion of the array to pointer to its first element) has the type sample_t * while the left operand has the type sample_t ** due to the declaration of the data member
sample_t **sample_arr;
There is no implicit conversion from the type sample_t * to the type sample_t **. So the compiler issued a message.
You should declare the data member like
sample_t *sample_arr;
and correspondingly the function declaration will look like
void print_new_sample_array(sample_t *sample_arr);
And within the function the call of printf will look like
printf("The array element is: %s\n", sample_arr[i].name);

passing argument 1 of 'recievematrix' from incompatible pointer type

#include<stdio.h>
Funtions prototypes
int functiondouble(int b);
void notreturnanything(int a, int b);
void byreference(int *b);
void receivevector(int v[]);
void recievematrix(int m[][1]);
int main() {
int c;
printf("%d\n",functiondouble(5));
notreturnanything(3,9);
c = 0;
byreference(&c);
printf("%d\n",c);
int a[10], b[3][4];
receivevector(a);
recievematrix((int)b); // <----- warning: passing argument 1 of 'recievematrix' from incompatible pointer type [enabled by default]|
return 0;
}
int functiondouble(int b) {
int a;
a = 2*b;
return a;
}
void notreturnanything(int a, int b) {
printf("%d\n",a+b);
}
Is ok. The two funtion no problems. They receive a single value without problems.
void byreference(int *b) {
*b = 7;
}
void receivevector(int v[]) {
scanf("%d", &v[0]);
}
void recievematrix(int m[][1]) {
scanf("%d", &m[1][1]);
}
This is a prove to see how work the arrays in C, but a pulls mistake and not where is the error.
This ...
int b[3][4];
... declares an array of three arrays of four ints. Given that declaration, in most expressions the array name b is converted to a pointer to its first element; that is, a pointer to an array of four ints (int (*)[4]);
This ...
int m[][1]
... declares an array of an unspecified number of arrays of one int. In the argument list of a function, it is converted to a pointer to an array of one int (int (*)[1]).
int (*)[4] is not compatible with int (*)[1]. To resolve the warning (which you certainly should do) without changing the type of variable b, change the signature of receivematrix() to
void recievematrix(int m[][4]);
or
void recievematrix(int (*m)[4]);
or even
void recievematrix(int m[3][4]);
For that matter, even
void recievematrix(int m[17][4]);
would silence the warning, though I wouldn't recommend using it.
Try
void recievematrix(int m[3][4])
And
recievematrix(b);

Compile time Error in C code [Returning an array pointer from function]

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>
int main()
{
int i, *ptr;
ptr = func();
for(i=0;i<20;i++)
{
printf("%d", ptr[i]);
}
return 0;
}
int * func()
{
int *pointer;
pointer = (int*)malloc(sizeof(int)*20);
int i;
for(i=0;i<20;i++)
{
pointer[i] = i+1;
}
return pointer;
}
ERROR:
Conflicting type of func.
Warning:
Assignment makes Pointer from integer without a cast [enabled by default]
Why am I getting this error?
Because you're calling func() without first declaring it. This causes the compiler to assume it's going to return int, but then you store that integer in a pointer which is of course rather suspicious.
Fix by moving func() to above main(), so the definition is seen before the call, or introduce a prototype before main():
int * func();
Also, functions taking no arguments should be (void) in C, and please don't cast the return value of malloc() in C.

Function pointer confusion

I'm trying to use function pointers and Abstract data types in c. This is my first time using it and I'm really confused. Anyways when I tried to compile this code I gave me an error. The first time I ran it worked. But when I change the arguments by switch a and b. It gave me the old answer and never updated.
typedef struct data_{
void *data;
struct data_ *next;
}data;
typedef struct buckets_{
void *key;
}buckets;
typedef struct hash_table_ {
/* structure definition goes here */
int (*hash_func)(char *);
int (*comp_func)(void*, void*);
buckets **buckets_array;
} hash_table, *Phash_table;
main(){
Phash_table table_p;
char word[20]= "Hellooooo";
int a;
a = 5;
int b;
b = 10;
/*Line 11*/
table_p = new_hash(15, *print_test(word), *comp_func(&a, &b));
}
int *print_test(char *word){
printf("%s", word);
}
int *comp_func(int *i,int *j){
if(*i < *j){
printf("yeeeeeeee");
}else{
printf("yeaaaaaaaaaaaaa");
}
}
Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *, void *)){
int i;
Phash_table table_p;
buckets *buckets_p;
hash_table hash_table;
table_p = (void *)malloc(sizeof(hash_table));
/*Setting function pointers*/
table_p -> hash_func = hash_func;
table_p -> comp_func = cmp_func;
/*Create buckets array and set to null*/
table_p -> buckets_array = (buckets **)malloc(sizeof(buckets_p)*(size+1));
for(i = 0; i < size; i++){
table_p -> buckets_array[i] = NULL;
}
return table_p;
}
This is the error message:
functions.c: In function 'main':
functions.c:11:26: error: invalid type argument of unary '*' (have 'int')
functions.c:11:45: error: invalid type argument of unary '*' (have 'int')
Helloyeaaaaaaaaaaaaa
New error:
functions.c:11:3: warning: passing argument 2 of 'new_hash' makes pointer from integer without a cast [enabled by default]
hash.h:29:13: note: expected 'int (*)(char *)' but argument is of type 'int'
functions.c:11:3: warning: passing argument 3 of 'new_hash' makes pointer from integer without a cast [enabled by default]
hash.h:29:13: note: expected 'int (*)(void *, void *)' but argument is of type 'int'
If you want to pass a function as a function-pointer, simply provide the name:
new_hash(15, print_test, comp_func);
or alternatively (and equivalently), use the & symbol to make it clear what's going on:
new_hash(15, &print_test, &comp_func);
You should declare function before using it. If you don't do this, the compiler assumes that it returns int, and gives you an error when you try to dereference it (since it's impossibole to dereference int).
EDIT:
you may also misunderstood the concept of function pointers. you should not pass the result of print_test(word) to new_hash - you should pass print_test itself. (also, change its return type)

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;
}

Resources