How can I create an array so that I can pass it as a pointer to this function?
void SomeFunction(double *a, double *b, double *c);
I made my 2d arrays like so (but I have errors):
static double matrix_a [MATRIX_DIM][MATRIX_DIM];
static double matrix_b [MATRIX_DIM][MATRIX_DIM];
static double matrix_c [MATRIX_DIM][MATRIX_DIM];
for (i=0;i<MATRIX_DIM;i++) {
for (j=0;j<MATRIX_DIM;j++) {
// initializing matrices here
}
}
Now I make pointers to the arrays:
double *a = &matrix_a;
double *b = &matrix_b;
double *c = &matrix_c;
And then call the function:
SomeFunction(a, b, c);
However I get the following error:
cannons.c: In function ‘main’:
cannons.c:29:14: warning: initialization from incompatible pointer type [enabled by default]
double *a = &matrix_a;
^
cannons.c:30:14: warning: initialization from incompatible pointer type [enabled by default]
double *b = &matrix_b;
^
cannons.c:31:14: warning: initialization from incompatible pointer type [enabled by default]
double *c = &matrix_c;
^
Why ?
double * means "pointer to a single double". However you have an array whose elements are arrays of double. So you in fact want a pointer to an array of double:
double (*a)[MATRIX_DIM] = &matrix_a[0]; // or matrix_a
when you access it as a[1][2] = 5.0;. Alternatively you could point to the entire array at once:
double (*x)[MATRIX_DIM][MATRIX_DIM] = &matrix_a;
but then you need an extra level of indirection to access it: (*x)[1][2] = 5.0;
You will need to use the same declaration in the parameter list too.
Related
I am trying to create an array of function pointers, so that I can print out output from the functions by using the pointers. (For an exercise from the Effective C book.)
#include <stdio.h>
#include <stdlib.h>
int a(void) { return 1; }
int b(void) { return 2; }
int c(void) { return 3; }
int main(void)
{
int(*func_arr)[3] = {&a, &b, &c};
printf("%d\n", (*func_arr)[0]);
}
However, when I compile it, I get the warnings
starting.c:10:26: warning: incompatible pointer types initializing 'int (*)[3]' with an expression of type
'int (*)(void)' [-Wincompatible-pointer-types]
int(*func_arr)[3] = {&a, &b, &c};
^~
starting.c:10:30: warning: excess elements in scalar initializer
int(*func_arr)[3] = {&a, &b, &c};
^~
And, when I run the program, I get an output of -443987883, while it should just be 1.
Does anyone know the solution for this? Thank you!
This declaration
int(*func_arr)[3] = {&a, &b, &c};
declares a pointer to the array type int[3].
So there is declared a scalar object of a pointer type that you are trying to initialize using a brace enclosed list of initializers with more than one initializer of an incompatible pointer type.
Instead you need to write
int ( *func_arr[3] )( void ) = { a, b, c };
The function designators used as initializers are implicitly converted to pointers to the functions.
So there is no need to write as for example &a though such an expression is also valid to be used as an initializer.
To simplify the array declaration you could introduce a typeded name for the function pointer type.
For example
typedef int ( *FnPtr )( void );
Now the array declaration can look the following way
FnPtr func_arr[3] = { a, b, c };
And to output results of function calls you need to write calls of printf like
printf("%d\n", func_arr[0]() );
I'd like to store the pointers of two arrays (*a and *b) created by malloc in a function.
For example, if &a[0]=0x0061FEC8 and &b[0]=0x007700FE, then the array to store these two pointers should be c[0]=0x0061FEC8 and c[1]=0x007700FE
void storePointers(int **ptrArray){
// create two arrays a and b by malloc
int *a = (int *)malloc(5*sizeof(int)); // a stores 5 integers
int *b = (int *)malloc(10*sizeof(int)); // b stores 10 integers
// create an array to store the pointers of a and b
*ptrArray = (int **)malloc(2*sizeof(int*));
(*ptrArray)[0] = a;
(*ptrArray)[1] = b;
}
int main(){
int *mArray = NULL;
storePointers(&mArray);
// these two lines should print 0x0061FEC8 and 0x007700FE
printf("mArray[0]: %p\n", mArray[0]);
printf("mArray[1]: %p\n", mArray[1]);
return 0;
}
This program actually worked. But the compiler displayed a warning message:
warning: assignment to 'int' from 'int *' makes integer from pointer without a cast [-Wint-conversion]
(*ptrArray)[0] = a;
warning: assignment to 'int' from 'int *' makes integer from pointer without a cast [-Wint-conversion]
(*ptrArray)[1] = b;
I assume int is common so the compiler fixed the problem by itself so that my program ran properly? I have another similar program, but it uses struct. So instead of a warning, I get an error of
Error: incompatible types when assigning to type 'myStruct' from type 'myStruct *'
I would like to know the root cause and solution to get rid of the warning and ultimately the error in my struct program.
If an array is int * then an array of arrays is int ** and if you want to return an array of arrays as an out parameter, then you need a pointer to that -- int ***. So you need to change the type of mArray as well as the ptrArray parameter:
void storePointers(int ***ptrArray){
// create two arrays a and b by malloc
int *a = (int *)malloc(5*sizeof(int)); // a stores 5 integers
int *b = (int *)malloc(10*sizeof(int)); // b stores 10 integers
// create an array to store the pointers of a and b
*ptrArray = (int **)malloc(2*sizeof(int*));
(*ptrArray)[0] = a;
(*ptrArray)[1] = b;
}
int main(){
int **mArray = NULL;
storePointers(&mArray);
// these two lines should print 0x0061FEC8 and 0x007700FE
printf("mArray[0]: %p\n", mArray[0]);
printf("mArray[1]: %p\n", mArray[1]);
return 0;
}
That should then work if you change the type from int to something else.
I did a function f which takes as input a (void*), convert it to a (int*) and print the value.
#include <stdlib.h>
#include <stdio.h>
void f(void* p)
{
int *pi = (int*)p;
printf("%d\n", *pi);
}
int main()
{
int x = 1;
int *px = &x;
void *pv = (void*)px;
f(pv);
return 0;
}
Is it possible to implement a function:
void f2(void** pp);
such that it performs the "same" operations of the function f? My goal is to learn how to convert a (int*) to a (void**) and viceversa.
EDIT: error and warning of #tadman code (I did a mistake)
fvv.c: In function ‘f2’:
fvv.c:10:12: warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ [-Wincompatible-pointer-types]
10 | int *pi = (int**)p;
| ^
fvv.c:12:17: error: invalid type argument of unary ‘*’ (have ‘int’)
12 | printf("%d\n", **pi);
|
EDIT2
fvv.c: In function ‘main’:
fvv.c:19:5: warning: passing argument 1 of ‘f2’ from incompatible pointer type [-Wincompatible-pointer-types]
19 | f2(&px);
| ^~~
| |
| int **
fvv.c:7:16: note: expected ‘void **’ but argument is of type ‘int **’
7 | void f2(void** p)
You can take any level of indirection you want, up to the blatantly, utterly absurd (void*******), but I'm not sure why this would be useful:
void f2(void** p)
{
// Note you must maintain the same level of indirection
int **pi = (int**)p;
// Since this is a ** pointer, it requires ** to fully de-reference
printf("%d\n", **pi);
}
To call this you need a pointer to a pointer:
int x = 1;
int *px = &x;
f2((void**) &px);
In C terms a pointer to a pointer is often interpreted to mean one of the two following things:
A two dimensional array
A mutable pointer argument
Neither of those apply here.
That being said, in C there's not a lot of rules as to what you can and can't convert. If you want to do it, C isn't going to get in your way, even if the resulting code makes no sense or will crash immediately when executed.
You can convert int* to void** and back again, C won't care, but you should have a really good reason for doing such a thing. Normally arbitrary pointers are almost always specified as void*, and as this can be recast into whatever you want, it's sufficient.
For example, you can specify void* as an argument when that pointer is actually int**, something you'll see quite often, as in thread_create taking a void* arg argument. That's not limited to mere pointers, you can cast to your heart's content.
GCC gives me an 'Initialization from incompatible pointer type' warning when I use the following code.
#include "mnist.h"
#include <stdio.h>
int main(void)
{
double** inputLayer = train_image;
}
train_image is a bidimensional array given by mnist header file that according to the autor is like that
train image : train_image[60000][784] (type: double, normalized, flattened);
array is not pointer to pointer.
int main()
{
double *pointer = &train_image[0][0];
double **inputLayer = &pointer;
}
If you have an array like this
double train_image[60000][784];
then a pointer to its first element should be declared like
double ( *inputLayer )[784] = train_image;
That is the expression train_image used as an initializer has the type double ( * )[784].
If it is needed then you can reinterpret the two-dimensional array as a one dimensional array using the following pointer declaration
double *inputLayer = ( double * )train_image;
I have warning:
note: expected ‘float (*)[100]’ but argument is of type ‘float (*)[100][100]’
My function looks like:
int readfile (float macierz_A[MAXSIZE][MAXSIZE], float macierz_B[MAXSIZE][MAXSIZE])
...
float A[MAXSIZE][MAXSIZE];
float B[MAXSIZE][MAXSIZE];
int r1;// = 3;
r1 = readfile(&A, &B);
Any idea?
Try to change this:
r1 = readfile(&A, &B);
Into this:
r1 = readfile(A, B);
Note that the & has been removed. Speaking in a very simple manner, you are passing a pointer to a multidimensional array, instead of the multidimensional array. (as you declared in the function declaration)
void f(int p[M][N]);
is equivalent to
void f(int (*p) [N]); //pointer to array of N elements
In your case N is 100 and the compiler expects expression of type int(*)[100]. But since A is (presumably) of type int[100][100] then &A is of type int(*)[100][100] which is what the error tells you. You must pass A, not its addess, i.e.
readfile(A, B)
Ok. The problem here is that you are passing the address of A and B, both of which are 2 dimensional arrays, but in the function "readfile" you are only accepting values of float[100][100].
The reason that this is a warning and not an error is because: float [][] is also interpreted as float *[] by the compiler (just like int * is equivalent to int [] ).
This is one level of indirection too much
r1 = readfile(&A, &B);
Just try
r1 = readfile(A, B);
Or, if you actually want a pointer to each matrix, change the function into
int readfile (float (*macierz_A)[MAXSIZE][MAXSIZE], float (*macierz_B)[MAXSIZE][MAXSIZE])