warning: assignment makes integer from pointer without a cast in array - c

I'm working with dynamic arrays and this is the declaration:
int *vetor = (int *) malloc (tam*sizeof(int));
vetorAleatorio (vetor, tam); //chamando função abaixo
but when I try to pass it as parameter to this function:
void vetorAleatorio(int **vet, int size) {
int i;
for (i=0; i<size; i++)
vet[i] = rand() %1000;}
I have the following errors:
[Warning] assignment makes pointer from integer without a cast
[Warning] passing arg 1 of `vetorAleatorio' from incompatible pointer type
Someone know how this is happening?

Your function syntax:
void vetorAleatorio(int **vet, int size)
should be:
void vetorAleatorio(int *vet, int size)
^
// remove one *
[Warning] assignment makes pointer from integer without a cast
if you use double * as int ** for vet, then its type mismatch as follows:
vet[i] = rand() %1000
^ ^
| int // rand() %1000 returns a int
type is int*
// vet[i] == *(vet + i) == *(pointer to pointer of int) = pointer int = int*
Warning-2: passing arg 1 of `vetorAleatorio' from incompatible pointer type
Understand In your code you according to void vetorAleatorio(int **vet, int size) declaration you are calling function in wrong way: vetorAleatorio (vetor, tam);, you are passing address of int = pointer to int, and argument need address of pointer to int = pointer to pointer to int.
You just need one rectification as I suggested above.

int **vet declares that the vet argument is a pointer to a pointer to int. i.e. an array of arrays of integers. It looks like you just want to pass a pointer to a single vector so you should declare the argument as type int* instead
void vetorAleatorio(int *vet, int size) {

Your function signature for vetorAleatorio is wrong - change:
void vetorAleatorio(int **vet, int size)
to:
void vetorAleatorio(int *vet, int size)
Also note that you should never cast the result of malloc in C, so change:
int *vetor = (int *) malloc (tam*sizeof(int));
to:
int *vetor = malloc (tam*sizeof(int));

vetor is of type int *, where veteroAleatorio is expecting an int **
You should have
void vetorAleatorio(int *vet, int size) {
int i;
for (i=0; i<size; i++)
vet[i] = rand() %1000;}

You have an extra *. This should work:
void vetorAleatorio(int *vet, int size)
You are passing in a pointer to an int (the variable vetor), so your function declaration should accept a pointer to an int.

Related

How do you pass an array to a function using pointers

I am trying to print an array through a function by using call by reference but keep getting a warning:
passing argument 1 of 'test' from incompatible pointer type [-Wincompatible-pointer-types]
I tried replacing test(&arr, n); with test(arr, n);, test(*arr, n);, test(&arr[], n);, test(*arr[], n);, test(&arr[], n);
but nothing worked, what am I doing wrong?
#include<stdio.h>
void test(int *a[], int b);
void main()
{
int arr[]={1, 2, 3, 4, 5}, i, n=5;
test(&arr, n);
}
void test(int *d[], int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d", *d[i]);
}
}
How do you pass an array to a function
Just by using a pointer of the array element type:
void test(int *a, int b);
If you then pass an array to the function:
test(arr);
... the C compiler will pass a pointer to the first element of the array (&(arr[0])) to the function.
Note that you don't use the & in this case.
Inside the function you can use array operations:
void test(int * arr)
{
arr[3] = arr[2];
}
(In your case: printf("%d\n", arr[n]);)
(This is true for any kind of pointer data type with exception of void *. The C compiler assumes that the pointer points to the first element of an array if you use array operations with pointer data types.)
"passing argument 1 of 'test' from incompatible pointer type"
As far as I know, [] in a function argument is not interpreted as array, but as pointer. For this reason, ...
void test(int *a[], int b);
... is interpreted as:
void test(int **a, int b);
... which means that the C compiler expects a pointer to an array of pointers (int *), not to an array of integers (int).
It's much simpler than that. In the example below I'm using size_t to express array size, it's an unsigned integer type specifically meant to be used for that purpose.
#include <stdio.h>
// you can use the size parameter as array parameter size
void test (size_t size, int arr[size]);
int main (void) // correct form of main()
{
int arr[]={1, 2, 3, 4, 5};
test(5, arr);
}
void test (size_t size, int arr[size])
{
for(size_t i=0; i<size; i++) // declare the loop iterator inside the loop
{
printf("%d ", arr[i]);
}
}

C - Copying array in other array as output argument

I am trying understand how pointers works in C. I am trying a simple case where an array, and a pointer to array are the arguments of a function which will copy the elements of the first one in the second one.
I have written this code
#include <stdio.h>
#define TAM 32
typedef int TablaArray[32];
void copyArray(TablaArray, TablaArray*, int);
void main(){
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++){
printf("%d - %d\n", t1[i], t2[i]);
}
}
void copyArray(TablaArray t1, TablaArray *t2, int tam){
for(int i = 0; i<tam-1; i++){
printf("%d\n", t1[i]);
*t2[i] = t1[i];
}
}
I am expecting to get something like this with the printf expression:
1 - 1
2 - 2
3 - 3
4 - 4
But definitely I don't know the way... I have been looking in stackoverflow and because I am sure this trivial question is already answered... but I didn't find it...
You need to make sure you are passing two int pointers pointing to both arrays. In your code only one of the arguments is a pointer. The code below should make it more clear:
#include <stdio.h>
void copyArray(int * arr1, int * arr2, int size);
int main(void)
{
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++)
{
printf("%d - %d\n", t1[i], t2[i]);
}
return 0;
}
void copyArray(int * arr1, int * arr2, int size)
{
for(int i = 0; i < size; i++)
{
printf("%d\n", arr1[i]);
arr2[i] = arr1[i];
}
return;
}
Edit: in what you have written, a TablaArray * is a pointer to an array of 32 ints, while you need an int *
typedef int TablaArray[32];
is bad practice
The problem is connected with array to pointer decay and then with pointer arithmetics:
Pointer decay means that if you pass an array-object of type int x[32] as argument to a function, then it "decays" to a pointer like int *, which points to the first element of the integer array. So be aware that if you pass an int x[32]-object, it's actually passed by reference (the array is not copied) and you may alter the contents of the array in the function.
Now pointer arithmetics:
Incrementing a pointer (or accessing an array through array subscripting) implicitly does pointer arithmetics, and the number of bytes added to the initial value depends on the type of the object to which the pointer points:
typedef int Array10[10];
Array10 arr = { 1,2,3,4,5,6,7,8,9,0 };
int *x = arr; // arrayOfInts decays to a pointer; x points to the &arr[0]
x++; // in terms of bytes, x is incremented by sizeof(int) bytes
int i = x[3]; // gets the int-value on the address of x + 3*sizeof(int)
Array10 *arr10ptr = arr;
arr10ptr++; // in terms of bytes, x is incremented by sizeof(Array10) bytes, which is 10*sizeof(int)
arr10ptr[3]; // 3*sizeof(Array10), i.e. 3*10*sizeof(int)
Now it should be clear why a function parameter being declared as a pointer to an array of int[32] behaves different from a function parameter being declared as an int[32].
So you could correct your program as follows, now knowing that TablaArray t2 will be a reference to the underlying array anyway:
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
Hope it helps.
Compile with warnings enabled. If you used gcc -Wall -Werror, you would get the following errors:
luis.c:10:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
void main(){
^~~~
luis.c: In function ‘main’:
luis.c:15:19: error: passing argument 2 of ‘copyArray’ from incompatible pointer type [-Werror=incompatible-pointer-types]
copyArray(t1, t2,4);
^~
luis.c:8:6: note: expected ‘int (*)[32]’ but argument is of type ‘int *’
void copyArray(TablaArray, TablaArray*, int);
^~~~~~~~~
cc1: all warnings being treated as errors
The first one is simple, it should be int main.
The second one is a bit harder to see exactly because you used a typedef. So your prototype is now
void copyArray(int *, int (*)[32], int);
With the second value being a pointer-to-array that by itself is a construct that is not used often.
Instead, you'd just need two pointers to int here, and the size of an array should perhaps use size_t instead:
void copyArray(int *, int *, size_t);
void copyArray(int *t1, int *t2, size_t n){
for (int i = 0; i < tam; i++) {
t2[i] = t1[i];
}
}
Finally, if you use a C99, C11 compiler, it could be nice to use the variable-length arrays arrays to tell that one of the parameters tell the sizes of the arrays; for that we need to reorder the parameters:
void copyArray(size_t, int[*], int[*]);
void copyArray(size_t n, int t1[n], int t2[n]) {
...
}
void copyArray(TablaArray, TablaArray, int); // prototype
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
this will help
// much faster
#include <string.h>
void copyArray(TablaArray t1, TablaArray t2, int tam){
memcpy(t2, t1, sizeof(t1[0]) * tam);
}
In Your Copy function you were copying the same value of T1 to T2 on the Address Of T2. you can do it with out pointers but pointers helps you to refer the Address

point to 2D array using double pointer [duplicate]

This question already has answers here:
Why cannot use pointer of pointer as parameter to declare a function receive pointer of array
(2 answers)
Closed 6 years ago.
Here is code :
void nextGeneration(int **board) {
int editBoard[row][col];
...
displayBoard(editBoard);
}
void displayBoard(int **board) {
...
}
I get this error msg:
GOL.c: In function ‘nextGeneration’: GOL.c:64: warning: passing
argument 1 of ‘displayBoard’ from incompatible pointer type GOL.c:28:
note: expected ‘int **’ but argument is of type ‘int (*)[(long
unsigned int)(col)]’
I just don't know how to point 2D array that will be accepted to void displayBoard(int **board) function.
How can I do that?
Thank you very much
An array passed to a function is implicitly converted to pointer to its first element.
So if such an array like
int editBoard[row][col];
is passed to a function as an argument it is converted to type int ( * )[col]. The types int( * )[col] and int ** are two incompatible different types.
If the compiler supports variable length arrays then you can declare your function like
void nextGeneration( size_t row, size_t col, int board[row][col] );
or
void nextGeneration( size_t row, size_t col, int board[][col] );
or
void nextGeneration( size_t row, size_t col, int ( *board )[col] );
These three declarations declare the same one function.
If the compiler does not support VLAs but the value col is defined as a constant (using #define or an enumerator) then you again can use these declarations.
Another approach is to interpret the array used as an argument as a one dimensional array. In this case you can declare the function like
void nextGeneration( int *board, size_t row, size_t col );
and pass the array like
nextGeneration( ( int * )editBoard, row, col );
A double pointer is not a 2D array, but you can do it using a single pointer
#include <stdio.h>
#define COL_WIDTH 2
int displayBoard(int *board, int row, int col)
{
// editBoard[row][col]
return board[(COL_WIDTH*row)+col];
}
int main(void)
{
int board[2][COL_WIDTH] = { {1,2}, {3,4} };
printf("%d\n", displayBoard((int *)(board), 1, 1));
printf("%d\n", displayBoard((int *)(board), 0, 1));
}
Like this
void nextGeneration(int **board) {
int editBoard[row][col];
...
displayBoard(editBoard);
}
void displayBoard(int board[][col]) {
...
}

Passing multidimensional arrays as arguments in functions in C

I am currently doing the fifteen exercise in CS50's Problem set 3. However, I am stuck in figuring out the syntax to pass a multi-dimensional array as an argument to a function. For instance, the following code (which prints out some numbers in an array) compiles and works:
#include <stdio.h>
void func(int array[], int size);
int main()
{
int size = 3;
int array[3] = {1,2,3};
func(array,size);
printf("Done\n");
}
void func(int array[], int size)
{
printf("%i %i %i\n", array[0],array[1], array[2]);
}
But this doesn't:
#include <stdio.h>
void func(int array[][], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int array[][], int size)
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
This is the error provided by clang:
test.c:3:20: error: array has incomplete element type 'int []'
void func(int array[][], int size);
^
test.c:13:20: error: array has incomplete element type 'int []'
void func(int array[][], int size)
Can anyone explain to me what's wrong with my syntax? I don't quite understand the error messages given to me by clang.
The function func() expects a pointer to int but you are passing a pointer to an array. Hence, the errrors.
It's because an array gets converted into a pointer to its first element when you pass it to a function.
You can change the function prototype and definition to receive a pointer to an array:
void func(int (*array)[3], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int (*array)[3], int size) {
...
}
Note that your array is initialized with size 3x3. So the array size has to 3x3 at least.
C99 allows to you pass dimensions. So you can write it like this too:
void func(int x, int y, int a[x][y]);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(3, 3, array);
printf("Done");
}
void func(int x, int y, int array[x][y])
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
An array is not a type in C! Internally, it is always handled as a pointer, hence, a pointer to the array is passed as argument and not the array itself.
If you intend to pass arrays as arguments (and not just pointers), you should rethink your design!
If you still need to do this wrap the array into a structure and pass the structure.
struct astruct
{
int size;
int array[3];
};
A declaration like int a[][] isn't sensible, since the compiler must know the size of all dimensions (except of the outermost) to calculate the memory address on access.
I.e. if an array is declared as
int array[][a][b];
The memory address for access to
array[2][1][3];
is calculated by
base_address + (2*a*b + 1*b + 3) * sizeof int
Without knowing a and/or b, this calculation would not be possible.
Simply tell the function to expect a multi-dimensional array:
void func (int array[3][3], int size);
Or if you want the function to be completely flexible:
void func (int x, int y, int array[x][y]);
You need to specify size of array when declaring prototype as well as while defining function . Right now it is of incomplete type .
Try this instead -
void func(int array[][3], int size)

Using and dereferencing (void**)

I would like to pass a "polymorphic" array of pointers to a function.
I can do the following without warnings:
foo (void* ptr);
bar()
{
int* x;
...
foo(x);
}
gcc apparently automatically casts x to a (void*), which is just dandy.
However, I get a warning when I do the following:
foo (void** ptr);
bar()
{
int** x; // an array of pointers to int arrays
...
foo(x);
}
note: expected ‘void **’ but argument is of type ‘int **’
warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
My question is: why is passing an (int*) as a (void*) argument not 'incompatible', but (int**) as a (void**) argument is?
Since all pointer types are the same size (right? it's been a while since I've used C),
I can still do something like:
void mainFunc1(int** arr, int len)
{
//goal is to apply baz to every int array
foo(baz, arr, len);
}
void mainFunc2(double** arr, int len)
{
//goal is to apply baz to every int array
foo(qux, arr, len);
}
// I PROMISE that if I pass in a (int**) as ptr, then funcPtr will interpret its (void*) argument as an (int*)
void foo(funcPtr f, void** ptr, int len)
{
for(int i = 0; i < len; i++)
{
f(ptr[i]);
}
}
void baz(void* x)
{
int* y = (int*)x;
...
}
void qux(void* x)
{
double* y = (double*)x;
...
}
The purpose for all the void pointers is so that I can use a function pointer applied to functions that will (down the stack) have different types of ptr arguments: some will take int arrays, some will take double arrays, etc.
Note: void* is generic. but void** is not. You can assign address of any type to void* variable but void** can be assigned address of void* variable only.
void* generic;
int i;
int *ptri = &i;
generic = ptri;
or
char c;
int *ptrc = &c;
generic = ptrc;
valid but following is an error:
void** not_generic;
int i;
int *ptri = &i;
int **ptr_to_ptr1 = &ptri;
void** not_generic = ptr_to_ptr1;
Error: assigning int** to void**.
Yes you can do like:
void** not_generic;
not_generic = &generic;
For generic array function simply use void* a as follows:
enum {INT, CHAR, FLOAT};
void print_array(void* a, int length, int type){
int i = 0;
for(i = 0; i < length; i++){
switch(type){
case INT:
printf("%d", *((int*)a + i));
break;
case CHAR:
printf("%c", *((char*)a + i));
break;
case FLOAT:
printf("%f", *((float*)a + i));
break;
}
}
}
You better write this function using macros.
Call this function as:
Suppose int:
int a[] = {1, 2, 3, 4};
print_array(a, sizeof(a)/sizeof(a[0]), INT);
Suppose char:
char a[] = {'1', '2', '3', '4'};
print_array(a, sizeof(a)/sizeof(a[0]), CHAR);
Because there is no generic pointer-to-pointer type in C.
Reference: C FAQ Question 4.9
The short answer is: anything that resembles
<datatype>* <variable_name>
can be passed in where the parameter declaration is of type void* because void* is generic. However, void** is not. So automatic casting fails.

Resources