How to cast back from void* ?
int *a[13][12];
void *b
int *c[13][12];
b = (void*) a;
c = (?????) b;
This
c = (int *[13][12])b;
says cast specifies array type
This
c = (int *[][])b;
says array type has incomplete element type.
Compiler is gcc (Ubuntu/Linaro 4.6.1)
In C, you cannot assign to an array, so since c is declared as an array of arrays of pointers to ints, you can't assign it directly.
You could however overwrite all of its items by assigning c[i][j] in turn inside a for loop, for example.
c and a are arrays not pointers, see above, you can use a pointer to a (2 dim) array like
int a[13][12] ={ 1,2,3 };
void *b = &a;
int (*c)[13][12] = b;
and all that without casts
You cannot assign directly to an array, or cast to an array type in C. However, since arrays decay to pointers, you can copy the data from a void * pointer (i.e.: memcpy) to an array and use it as an array, e.g.:
#include <stdio.h>
#include <string.h>
int main() {
int a1=1, a2=2, a3=3, a4=4;
int *a[2][2] = { { &a1, &a2 }, { &a3, &a4 } };
printf("%d %d %d %d\n", *a[0][0], *a[0][1], *a[1][0], *a[1][1]);
void *b;
b = (void*) a;
int *c[2][2];
memcpy(c, b, sizeof(c));
printf("%d %d %d %d\n", *c[0][0], *c[0][1], *c[1][0], *c[1][1]);
return 0;
}
Compiling and running the following program will give you:
1 2 3 4
1 2 3 4
However, c and a are two different arrays now.
Related
Why my code output is 5 and 0, not 6 and 5?
I think I should get 6 and 5. I am a beginner.
#include <stdio.h>
int swap(int a,int b);
int main()
{ int x =5;
int y =6;
printf("%d %d\n",x,y);
int number[2]={swap(x,y)};
x=number[0];
y=number[1];
printf("%d %d\n",x,y);
return 0;
}
int swap(int a,int b)
{
return b,a;
}
There are several things wrong here.
First, you can't return multiple values in C, like you can in Python. return b, a; uses the comma operator, which evaluates both its operands and returns the second one. So this is equivalent to just return a;.
Second, your array initializer is only initializing the first element of the array. There's only one expression in the initialization braces, so that initializes number[0]. The remaining elements of the array are initialized by default to 0.
Combining both of these, it's equivalent to:
int number[2] = {y, 0};
I can see you are new to C programming. The problem is in your swap() function. You're using a language construct that does not exist in C, namely tuples. Check out pointers for a proper way to return multiple values from a function.
This function ...
int swap(int a,int b)
... returns one int, as its prototype says.
This statement ...
return b,a;
... involves C's comma operator ,, which evaluates its left-hand operand, discards the result, then evaluates to the value of its right-hand operand. Since evaluating b has no side effects in your case, that return statement is equivalent to
return a;
In C, it is valid to initialize an array with fewer explicit elements than the length of the array. For an automatic (local, non-static) array such as yours, as long as at least one element is initializer, all elements not explicitly initialized are implicitly initialized (to 0 in the case of int elements). Thus, for your implementation of swap(), this ...
int number[2]={swap(x,y)};
... is equivalent to
int number[2] = { x, 0 };
, which explains the output.
Here is a way to solve your problem.
#include <stdio.h>
void swap(int *a,int *b);
int main()
{
int x = 5;
int y = 6;
swap(&x, &y);
printf("post swap x = %d, y = %d\n", x, y);
return 0;
}
// No need to return anything, we change the x, y values using the pointer
// This is passing by reference. Instead of passing the value, we are
// passing the reference (i.e address of the variable). swap function can
// now directly access the values and change them
void swap(int *a, int *b)
{
int tmp;
printf("Swap got a = %d, b = %d\n", *a, *b); // Note: we access value of a pointer using * in front of the pointer varaible
tmp = *a;
*a = *b;
*b = tmp;
}
outputs:
bhakta: /tmp$ cc x.c
bhakta: /tmp$ ./a.out
Swap got a = 5, b = 6
post swap x = 6, y = 5
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 want to use the C function called is_subsetOf() in two different ways:
Way 1: int* a and int* b are arrays with sizes >=2.
Way 2: int* a has size >=2, but int* b is only size 1, which means b is an int.
How can I force C to be okay with int* b being of size 1? Or is this not possible in C? An int IS an array of size 1??
int* is_in(int *left_hand, int n_l, int *right_hand, int n_r) {
int *get_bool;
get_bool = malloc(sizeof(int)*n_l);
for (int i=0; i<n_l; i++) {
if (is_subsetOf(right_hand, n_r, *(left_hand+i), 1)) {
*(get_bool+i) = 1;
}
}
return (get_bool);
}
int desc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int is_subsetOf(int *a, int n_a, int *b, int n_b) {
qsort(a, n_a, sizeof(int), desc);
qsort(b, n_b, sizeof(int), desc);
int v = includes(a, n_a, b, n_b);
return(v);
}
Here are the messages I get from the compiler. It's just a warning, I know, but I'd like everything to be clean.
tmp.c: In function ‘is_in’:
tmp.c:73:47: warning: passing argument 3 of ‘is_subsetOf’ makes pointer
from integer without a cast [-Wint-conversion]
if (is_subsetOf(right_hand, n_r, *(left_hand+i), 1)) {
~~~~~~~~~^~~
tmp.c:37:39: note: expected ‘int *’ but argument is of type ‘int’
int is_subsetOf(int *a, int n_a, int *b, int n_b) {
int* a and int* b are arrays with sizes >=2.
No, they are pointers and they don't have any size. You probably meant that you pass arrays through them, but they are not arrays. Know that there is a difference.
An int IS an array of size 1
No, int a[1]; is an array of size 1; int a; is just int. But arrays can decay into pointers to their first element and variables have addresses, so this is correct:
int a[1];
int b;
int* ptr1 = a;//Points to the a[0]
int* ptr2 = &b;
Both are now same type and can be used in the same way. Of course you don't know if the int is followed by any more ints in memory, that kind of checking is up to the programmer (usually by passing the length param as you do). The following is the code you are actually looking for:
is_subsetOf(right_hand, n_r, left_hand+i, 1)
Pointers can be incremented, left_hand+i will point to the i-th int after the int to which left_hand currently points to. Again, validity of such pointer is up to programmer.
The compiler warning is quite important here, because *(left_hand+i) is of type int and the compiler warns that it will treat is as int*. Essentially looking that the value of int as an address to memory. That's not at all what you want and it is an error.
To pass a 1D array to a function, we do this:
#include <stdio.h>
#include <stdlib.h>
void func(int *arr, int n)
{
// code here
}
int main()
{
int arr[] = {......}; // declare array
int n = sizeof(arr)/sizeof(arr[0]);
func(arr); // calling function func
return 0;
}
To pass a 2D array to a function, we do this:
#include <stdio.h>
#include <stdlib.h>
void func(int arr[][2])
{
// code here
}
int main()
{
int arr[3][2]; // declare 2D array
func(arr); // calling function func
return 0;
}
So while passing a pointer array to a function, can we do something like this?
#include <stdio.h>
#include <stdlib.h>
void func(int **arr, int n)
{
// code here
}
int main()
{
int *arr[] = {......}; // declare array of pointers
int n = sizeof(arr)/sizeof(arr[0]);
func(arr, n); // calling function func
return 0;
}
I am confused with pointers and arrays to be honest. It took me a long time to figure out how to pass a 2D array. I tried searching other similar questions, but to no avail. Please help me with: Passing a pointer array to a function. Also, any links where I can clear the confusion will be really appreciated.
In your last example, you have an array of pointers.
And yes, that would work, check for example this toy example:
#include <stdio.h>
#include <stdlib.h>
void func(int **arr, int n) {
// print equal to arr[0][1]
printf("%d %d\n", n, *arr[1]);
}
int main(void) {
int a = 1, b = 2, c = 3;
// set the points of a, b, and c, to arr[0][0..2];
int *arr[] = {&a, &b, &c};
int n = sizeof(arr)/sizeof(arr[0]);
printf("%d %d\n", n, *arr[1]);
func(arr, n);
return 0;
}
Output:
3 2
3 2
I am confused with pointers and arrays to be honest. It took me a long time to figure out how to pass a 2D array.
This confusion is very widespread. It stems from the fact that you cannot pass arrays in C, but the language allows a syntax that makes it look like you could.
So, as you can't pass an array to a function, what you do instead is pass it a pointer to the first array element and, if needed, the size of the array. Inside the function, you can use that pointer for accessing the array, and the syntax looks the same as if it would be an actual array. This also needs some explanation:
[], the indexing operator, works by adding the index to a given pointer and dereferencing the resulting pointer. Therefore, writing a[5] is exactly the same as *(a+5).
This even works if a is an actual array (and not a pointer), because an array evaluates to a pointer to the first element in most contexts (there are exceptions like the sizeof operator).
To make things more complicated, C allows to declare functions that look as if they were taking arrays, e.g. you can write:
void foo(int bar[]);
There's a rule in the C standard that says function parameter types are subject to "type adjustment": Any parameter of an array type is automatically adjusted to the corresponding pointer type. So, the function above is actually the same as
void foo(int *bar);
Therefore, better forget about passing arrays (I'd even recommend to not use the array syntax in function parameters, but that's subject to debate) -- you always pass pointers.
With this knowledge, you can easily construct correct examples for all your cases:
(1) "Normal" array:
void foo(int bar[], size_t n); // with type adjustment
void foo(int *bar, size_t n); // what it really means
// call like
int a[5];
foo(a, 5);
(2) 2D array:
A 2D array is an array of arrays, so it's first element is itself an array -> you would pass a pointer to an array
void foo(int bar[][10], int n); // with type adjustment, 2d array of n x 10
void foo(int (*bar)[10], int n); // what it really means
// call like:
int a[5][10];
foo(a, 5);
(3) Array of pointers:
An array of pointers is often used as an alternative to a 2d array -- as the elements are just pointers, they can point to single values or arrays of different lengths, but the drawback is that you don't have the whole data as a single block in memory, as would be the case with a real 2d array. As this is just an array of pointers, it looks very much like a "normal" array in use:
void foo(int *bar[], int n); // with type adjustment
void foo(int **bar, int n); // what it really means
// call like:
int *a[5];
foo(a, 5);
Final note: You will often read that arrays "decay as pointers" in C. That's no official wording, but very widespread. If you combine the rule that an array identifier evaluates to a pointer in most contexts (e.g. when passing it to a function) with the rule of type adjustment for function parameters, the result is that you write array syntax everywhere, but get pointers, so that's the meaning of "decaying".
There is actually no differences among 1-D array, 2-D array, X-D array and pointer array. All of them are just consequent memory area.
1-D array:
int arr[8];
int *addr = arr;
| arr[0] | ...*6... | arr[7] |
^ ^
| |
addr addr+7
2-D array:
int arr[4][2]
int *addr = arr[0];
| arr[0][0] | ...*6... | arr[3][1] |
^ ^
| |
addr addr+7
3-D array:
int arr[2][2][2];
int *addr = arr[0][0];
| arr[0][0][0] | ...*6... | arr[1][1][1] |
^ ^
| |
addr addr+7
pointer array:
typedef pointer int*;
...
int a0[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int a1[7] = {0, 1, 2, 3, 4, 5, 6};
...
int a7[1] = {0};
pointer arr[8] = {a0, a1, a2, a3, a4, a5, a6, a7};
pointer *addr = arr;
| arr[0] = a1 | ...*6... | arr[7] = a7 |
^ ^
| |
addr addr+7
Defining an X-D array can be implemented as following:
typedef data_type int;
typedef struct X-Array
{
int d1;
int d2;
...
int dx;
data_type *data;
} X-Array;
X-Array *create_X_Array(int d1, int d1, ..., int dx)
{
X-Array *arr;
if ((arr = malloc(sizeof(X-Array))) == NULL)
return NULL;
if ((arr->data = malloc(sizeof(data_type * d1 * d2 * ... * dx))) == NULL)
{
free(arr);
return NULL;
}
arr->d1 = d1;
arr->d2 = d2;
...
arr->dx = dx;
return arr;
}
void main()
{
int (*d)[10];
d[0] = 7;
d[1]=10;
printf("%d\n",*d);
}
It should print 10 but compiler is showing error such as follows:
test.c:4:7: error: incompatible types when assigning to type ‘int[10]’ from type ‘int’
Note that I have included some errors , not all.
As noted by chris, d is a pointer to an array. This means you use the variable improperly when you access it, but also that you will access random memory unless you assign d to point to a valid array.
Change your program as follows:
int main(void)
{
int (*d)[10]; /* A pointer to an array */
int a[10]; /* The actual array */
d = &a; /* Make `d` point to `a` */
/* Use the pointer dereference operator (unary prefix `*`)
to access the actual array `d` points to */
(*d)[0] = 7;
(*d)[1] = 10;
/* Double dereference is okay to access the first element of the
arrat `d` points to */
printf("%d\n", **d);
return 0;
}
In C, [] is the same as *, the pointer syntax. Thus the following lines are the same:
int** array2d1;
int* array2d2[];
int array2d3[][];
To relate to a closer example, the main function has the following popular forms:
int main(int argc, char** argv){ ... }
or
int main(int argc, char* argv[]){ ... }
Thus
int (*d)[10]
is the same as
int* d[10]
which is the same as
int** d;
int firstArray[10];
d = &firstArray;
Effectively, you are creating a pointer to a pointer (which is a pointer to an array) and allocating the first pointer to an array that 10 elements. Therefore, when you run the following lines:
d[0] = 7;
d[1] = 10;
You are assigning the 1st array's address to 7 and the second array's address to 10. So as Joachim has mentioned, to assign values, you need to deference twice:
(*d)[0] = 7
(*d)[1] = 10
Which says "Assign 7 to the 0th index at the value pointed by d". I hope that makes sense?
d is a pointer to an array of 10 ints.
int (*d)[10] is the declaration for a point to an array of 10 ints.
vs.
int *d[10], which is an array of 10 int pointers.
For more complex syntax like this (usually involving pointers), I use cdecl to help me decode it.
It's used in this form
int d[10]
I guess you are mistaken that d must be a "kind of pointer" and therfor you put an * before the d.
But that's not what you want. You wan to name an array of integer and the notation for that is seen above.
Concept of pointer can get confusing sometimes in C.
Consider an array int d[6] = {0,1,2,3,4,5}
Then, *d is equivalent to d[0]. d is itself an pointer to an array and *d dereferences that pointer and gives us the value.
Hence, following code would print the same values:
int main()
{
int (d)[10];
*d = 7;
*(d + 1)=10;
printf("%d\n",*d);
printf("%d\n",d[0]);
return 0;
}
result:
7
7
Please see http://codepad.org/LYY9ig1i.
If you change your code as follows:
#include<malloc.h>
int main()
{
int *d[10]; //not (*d)[10]
d[0] = (int *)malloc(sizeof(int *) * 10);
d[0][0] = 7;
printf("%d\n",d[0][0]);
return 0;
}
Hope this helps you!