Pointer of void array - c

I have an array of void-Pointers and want to access the elements (inititialize them), but it do not work:
void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);
int i=0;
for(i=0; i<10; i++)
*(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too
I guess, the reason why this won´t work is that on the left side is the result of element i. But i don´t have an idea how to do this

There are two ways to initialize arrays in C:
On the stack (which will handle memory for you since it will be cleaned up when your function ends)
In the heap (which will require you to handle allocation and freeing on your own).
If you would like to use the stack, you could initialize your array like this...
#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
You can similarly define your array in the heap as follows...
#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
free(arr);
It is important to remember that an array (besides arrays assigned in the stack, which have some additional attributes such as length) is essentially just a pointer to the first element, and the operation arr[i] is the same as moving i*sizeof(elem) bytes away from the first element, and accessing the memory there. If you would like to get a pointer to the ith index in the array, then you would use notations such as...
void *indexPtr = arr + i;
or
void *indexPtr = &( arr[i] );
In this fashion, an array of void*'s would be of type void **, since the variable is a pointer to the first member of the array, which is a pointer. This can be a bit confusing, but just always try to keep in mind what type the elements of the array are, and creating a pointer to them. So if the array is of type int, then the array would be of type int or int[], but if you are storing pointers to integers, you would initialize an array of type int * in either of these two forms...
int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];
Also note that you are storing pointers, so if you run the code...
int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = &i;
}
Although it may seem to be that the values pointed to in the array would be as follows- [0, 1, 2, 3], but in reality it would be [4, 4, 4, 4], since what you actually have is an array of pointers all pointing to the variable i in your function, so whenever you change that, the values pointed to in the array will all be changed.
I hope this helped

You need to change this line
void* arr = (void*)malloc(sizeof(void*)*10);
to this
void** arr = malloc(sizeof(void*)*10);

You can't dereference a void pointer. That's the whole point of void pointers.
Dereferencing a pointer provides you with access to the item that's found at the address the pointer points to. With a void pointer, however, you don't know how large the target object is (is it a 1B character or a 100B struct?). You have to cast it to a specific pointer type before dereferencing it.
Adding (or subtracting) an integer i to a pointer is then defined as adding i-times sizeof(*pointer) to the pointer's content. (You can only tell sizeof(*pointer) if your pointer has a specific type. Pointer arithmetic with void pointers makes no sense).
As for (arr+n)= anyptr;, arr+n is just an address. It's not a value you can assign something to (not an lvalue).

Related

C: Array of memory addresses?

I'm trying to make a sort of container for multiple different structs. Unfortunately C only allows type specific arrays, meaning I'd have to make a different array for each type of struct.
The current solution I came up with is a container that holds memory addresses. This way the program can just pass the memory address of one of the elements to a function.
Currently the only code I have is a failed attempt using void pointers (not really familiar with pointers and memory addresses yet unfortunately)
The following is my test code I was writing to try and understand how this stuff works:
void* arr[10]={};
int len=0;
int n[5]={1,2,3,4,5};
for (int i=0;i<5;i++) { //add pointers nums in n to arr
arr[i]=(void*)(&n[i]);
len++;
}
for (int i=0;i<len;i++) { //print contents of arr
printf("%p\n", (void*)arr[i]);
printf("\t%d\n", arr[i]); //trying to print actual value (eg. 2 for index 2) but not really sure how to...
}
Thanks!
Your approach is correct but there is some stuff missing...
In C any object pointer can be converted to a void-pointer and back to a pointer of the original type. So an int-pointer can be converted to a void-pointer an back to an int-pointer. And a float-pointer can be converted to a void-pointer an back to an float-pointer.
So using an array of void-pointers to store pointers to different object types is a fine approach.
But... in order to convert the void-pointer back to the original type, you need to know what the original type was. If you just saves the void-pointer, you don't have that information.
Instead consider something like:
struct gp
{
void* p;
unsigned type_tag;
}
#define INT_TYPE 0
#define FLOAT_TYPE 1
and use it like:
struct gp arr[2];
int n = 42;
float f = 42.42;
arr[0].p = &n;
arr[0].type_tag = INT_TYPE;
arr[1].p = &f;
arr[1].type_tag = FLOAT_TYPE;
for (int i=0; i < 2; ++i)
{
if (arr[i].type_tag == INT_TYPE)
{
int* p = (int*)arr[i].p; // Cast void-pointer back to int-pointer
printf("%d\n", *p); // Get int-value using *p, i.e. dereference the pointer
}
else if (arr[i].type_tag == FLOAT_TYPE)
{
int* p = (float*)arr[i].p; // Cast void-pointer back to float-pointer
printf("%f\n", *p); // Get float-value using *p, i.e. dereference the pointer
}
}
You need to derefence the pointer stored in the array. You also need to cast it to the original type of the referenced objects.
printf("\t%d\n", *(int *)arr[i]);

error: lvalue required as left operand of assignment 11 | (*pt+9) = ((int *)malloc(1*sizeof(int)));

int *pt[10];
*pt = (int *) malloc(10*sizeof(int));
until this line everything is ok:-
but as soon as i try to allocate memory to a specific address inside a array the ERROR occurs.
(*pt+9) = (int *)malloc(1*sizeof(int));
int* pt[10] is an array of pointers and *pt = (int *) malloc(10*sizeof(int)); is the wrong way to allocate memory for an array of pointers.
If the intention is to allocate an array of 10 integers, the code should be:
int* pt = malloc(10 * sizeof(int));
If the intention is to allocate room for each pointer in an array of 10 pointers, then each and every pointer needs to be initialized:
int* pt[10];
for(int i=0; i<10; i++)
pt[i] = malloc(n * sizeof(int)); // where n is some array size
(*pt+9) Doesn't work reliably in case you allocated 10 int. pt in the original example is an array of pointers, and when an array is used in an expression it "decays" into a pointer to the first element. In this specific case it is equivalent to int**. And when you de-reference that you end up with int* type. Then the + 9 does pointer arithmetic on int types rather than int* types.
None of it makes sense, simply do pt[9] in case you intend to access the last pointer item in the array. In general always use arr[i] style before *(arr + i) because the latter is harder to read and much easier to get wrong.

The difference between pointer in 2D and 1D array

I practiced today some C code, especially array with return function and pointers.
And I found some code which were really confusing and want to know why it is.
So I have first a function which print all elements out of the array.
void function(int *arr)
{
...
printf("%d, arr[i]);
}
Now in main I have a 2D array and a 1D array.
int array2D[2][2] = {{1,2}, {3,4}};
int array1D[3] = {1,2,3};
function(*array2D); // Why do I need here the derefernce pointer
function(array1D); // why I don't need here the deference pointer
And in another case:
void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
for (int i=0; i<10; i++)
{
/* Passing addresses of array elements*/
disp(&arr[i]); // why i need here & and above in the function not
}
}
This is really confusing me right now. Can someone explain me this?
The first line
function(*array2D);
is equivalent to
function(array2D[0]);
So you are passing the first array [1,2]. In C an array decays into a pointer
when it is passed to a function.
However, your function function1 should also get the number of
elements of the array.
void function(int *arr, size_t len)
{
size_t i;
for(i = 0; i < len; ++i)
printf("%d\n", arr[i]);
}
Then you can call it2
int array2D[2][2] = { { 1,2} ,{3,4}};
int array1D[3] = {1,2,3};
function(*array2D, sizeof *array2D / sizeof **array2D);
function(array1D, sizeof array1D / sizeof *array1D);
disp (&arr[i]); // why i need here & and above in the function not
Because arr[i] would give you the value stored at the position i, disp
expects a pointer, so you use the &-operator which returns the address of the
array at the position i, which is also equivalent to arr + i.
1Don't call your functions function. Technically that is valid name, but it
would be better if you give your function more explicit names so that just by
reading the name, you know what the functions does.
2Note that sizeof array / sizeof *array only works with arrays. If you have a
function and you expect an array, you will get only a pointer to the array.
In this case you also would need to pass the length of the array.
We're used to the fact that int mike[10] decays to int *, which points to the first thing in the array. So it seems like int sam[5][10] might also decay to int * pointing to the first element of the array. But int sam[5][10] is not a "two-dimensional array of int" that decays to an int pointer, it's an array of five arrays of ten integers. The first thing in sam is the first of the five arrays, so sam decays to a pointer to an array of ten integers, which type is written int (*)[10], though it rarely is written.
So your array2D decays to a different type than integer pointer, which is why your call function(array2D); creates a type mismatch. But your call function(*array2D); does work because (as noted above) *array2D is the same as array2D[0], which is an array of integers, and does decay to int *.
For your second case, arr is an array, but arr[i] is an int, since it is just one position in the array. The ampersand operator makes a pointer of what it operates, so &arr[i] is a pointer, and the call works.

Trouble working with 2d array passed by reference C

So I am working on an assignment and I am having trouble figuring out how to use this 2d array which was passed by reference.
What I am given is this
int main(){
//cap and flow initialized
maximum_flow(1000, &(cap[0][0]), &(flow[0][0]));
}
So I wanted to copy the contents of cap over to another 2d array I dynamically allocated, but after hitting an error I decided to print out the values I have in cap2 and capacity, I'm not getting back all the values that I should.
void maximum_flow(int n, int *capacity, int *flow){
int **cap2;
cap2 = (int**) malloc(sizeof(int *)*n);
for (i = 0; i < n; i++)
{
cap2[i] = (int*) malloc(sizeof(int)*n);
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cap2[i][j] = (*(capacity + i*n + j));
(*(flow + i*n + j)) = 0;
}
}
}
This isn't going to be a terribly useful answer, since your code doesn't actually show the problem described; based on what's presented, I see no obvious reason why cap and cap2 shouldn't have the same contents by the end of the maximum_flow function. But I'd like to offer some background and a suggestion.
I'm going to assume cap and flow are declared as n by n arrays of int in main, where n is known at compile time.
The reason your instructor is using this interface is that passing multidimensional arrays as function arguments is problematic in C. Remember that unless it's the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaraiton, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
So, assuming a declaration like
int cap[10][10];
int flow[10][10];
the expressions cap and flow will each "decay" to type int (*)[10] (pointer to 10-element array of int). So if you wrote your function call as
maximum_flow( 1000, cap, flow );
then the function definition would have to be written as
void maximum_flow( int n, int (*cap)[10], int (*flow)[10] ) { ... }
or
void maximum_flow( int n, int cap[][10], int flow[][10] ) { ... }
In the context of a function parameter declaration, T a[][N] and T (*a)[N] mean the same thing.
The size of the outer dimension has to be specified in the array pointer declaration, and the problem is that a pointer to a 10-element array is a different, incompatible type from a pointer to an any-value-other-than-10-element array; thus, maximum_flow could only ever be used for N x 10-element arrays, limiting its usefulness. One way around this problem is to have the function receive an explicit pointer to the first element, and treat that pointer as a 1D array of size N * M.
Long story short, since you're treating your input parameters as 1D arrays, you are probably better off creating cap2 as a 1D array as well:
int *cap2 = malloc( sizeof *cap2 * n * n );
...
cap2[i * n + j] = capacity[i * n + j]; // use array subscript notation instead
flow[i * n + j] = 0; // of explicit dereferences
From the code you've posted, it's not clear what maximum_flow is supposed to do, nor why you need cap2. Note also that at some point you need to free the memory allocated to cap2, otherwise you have a memory leak.
If you're using a C99 or later compiler, you should be able to use a variable-length array instead of malloc:
int cap2[n * n]; // or int cap2[n][n], but like I said above, if you're
// treating your inputs as 1D arrays, you should also treat
// cap2 as a 1D array.
The advantage of a VLA is that you don't need to know the size at compile time, and it's treated like any other auto variable, meaning the memory for it will be released when the function exits.
The disadvantage of a VLA is that you can't use it as anything but a local variable; you can't have a VLA as a struct or union member, nor can you declare one static or at file scope. Neither can you explicitly initialize a VLA.

Returning a two-dimensional array in C?

I recently started programming C just for fun. I'm a very skilled programmer in C# .NET and Java within the desktop realm, but this is turning out to be a bit too much of a challenge for me.
I am trying to do something as "simple" as returning a two-dimensional array from a function. I've tried researching on the web for this, but it was hard for me to find something that worked.
Here's what I have so far. It doesn't quite return the array, it just populates one. But even that won't compile (I am sure the reasons must be obvious to you, if you're a skilled C programmer).
void new_array (int x[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
return x;
}
And usage:
int x[n][n];
new_array(x);
What am I doing wrong? It should be mentioned that n is a constant that has the value 3.
Edit: Here's a compiler error when trying to define the constant: http://i.imgur.com/sa4JkXs.png
C does not treat arrays like most languages; you'll need to understand the following concepts if you want to work with arrays in C.
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. This result is not an lvalue; it cannot be the target of an assignment, nor can it be an operand to the ++ or -- operators.
This is why you can't define a function to return an array type; the array expression will be converted to a pointer type as part of the return statement, and besides, there's no way to assign the result to another array expression anyway.
Believe it or not, there's a solid technical reason for this; when he was initially developing C, Dennis Ritchie borrowed a lot of concepts from the B programming language. B was a "typeless" language; everything was stored as an unsigned word, or "cell". Memory was seen as a linear array of "cells". When you declared an array as
auto arr[N];
B would set aside N "cells" for the array contents, along with an additional cell bound to arr to store the offset to the first element (basically a pointer, but without any type semantics). Array accesses were defined as *(arr+i); you offset i cells from the address stored in a and dereferenced the result. This worked great for C, until Ritchie started adding struct types to the language. He wanted the contents of the struct to not only describe the data in abstract terms, but to physically represent the bits. The example he used was something like
struct {
int node;
char name[14];
};
He wanted to set aside 2 bytes for the node, immediately followed by 14 bytes for the name element. And he wanted an array of such structures to be laid out such that you had 2 bytes followed by 14 bytes followed by 2 bytes followed by 14 bytes, etc. He couldn't figure out a good way to deal with the array pointer, so he got rid of it entirely. Rather than setting aside storage for the pointer, C simply calculates it from the array expression itself. This is why you can't assign anything to an array expression; there's nothing to assign the value to.
So, how do you return a 2D array from a function?
You don't. You can return a pointer to a 2D array, such as:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
The downside to this approach is that N must be known at compile time.
If you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you could do something like the following:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
If you don't have variable-length arrays available, then at least the column dimension must be a compile-time constant:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
You can allocate memory piecemeal into something that acts like a 2D array, but the rows won't necessarily be contiguous:
int **func4( size_t rows, size_t cols )
{
int **p = malloc( sizeof *p * rows );
if ( p )
{
for ( size_t i = 0; i < rows; i++ )
{
p[i] = malloc( sizeof *p[i] * cols );
}
}
return p;
}
p is not an array; it points to a series of pointers to int. For all practical purposes, you can use this as though it were a 2D array:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
Note that C doesn't have any garbage collection; you're responsible for cleaning up your own messes. In the first three cases, it's simple:
int (*arr1)[N] = func(rows);
// use arr[i][j];
...
free( arr1 );
int (*arr2)[cols];
func2( rows, cols, &arr2 );
...
free( arr2 );
int (*arr3)[N];
func3( rows, &arr3 );
...
free( arr3 );
In the last case, since you did a two-step allocation, you need to do a two-step deallocation:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
Your function return void, so the return x; line is superfluous. Aside from that, your code looks fine. That is, assuming you have #define n 3 someplace and not something like const int n = 3;.
You can't return an array in C, multidimensional or otherwise.
The main reason for this is that the language says you can't. Another reason would be that generally local arrays are allocated on the stack, and consequently deallocated when the function returns, so it wouldn't make sense to return them.
Passing a pointer to the array in and modifying it is generally the way to go.
To return (a pointer to) a newly-created array of dimensions known at compile time, you can do this:
#define n 10 // Or other size.
int (*new_array(void))[n]
{
int (*x)[n] = malloc(n * sizeof *x);
if (!result)
HandleErrorHere;
for (int i = 0; i < n; ++i)
for (int o = 0; i < n; ++o)
x[i][o] = InitialValues;
return x;
}
…
// In the calling function:
int (*x)[n] = new_array();
…
// When done with the array:
free(x);
If the size is not known at compile time, you cannot even return a pointer to an array. C does support variable-length arrays but not in the return types of functions. You could instead return a pointer to a variable-length array through a parameter. That requires using a parameter that is a pointer to a pointer to an array of variable length, so it gets somewhat messy.
Also, the preferred choices between allocating an array in the caller dynamically, allocating an array in the caller automatically, allocating an array in the called function dynamically and using variable-lengths arrays or fixed-length arrays or even one-dimensional arrays with manual indexing depend on context, including what how large the array might be, how long it will live, and what operations you intend to use it for. So you would need to provide additional guidance before a specific recommendation could be made.
In C there's only pass/return by value (no pass by reference). Thus the only way of passing the array (by value) is to pass its address to the function, so that it can manipulate it through a pointer.
However, returning by value an array's address isn't possible, since by the time control reaches the caller, the function goes out of scope and its automatic variables go down with it too. Hence if you really have to, you can dynamically allocate the array, populate and return it, but the preferred method is passing the array and leaving the onus of maintaining the array to the caller.
As for the error, the only warning I get in GCC for this is warning: 'return' with a value, in function returning void which is simply meaning that you shouldn't return anything from a void function.
void new_array (int x[n][n]); what you're really doing here is taking a pointer to an array of n integers; the decayed type is int (*x)[n]. This happens because arrays decay into pointers generally. If you know n at compile time, perhaps the best way to pass is:
#define n 3
void new_array (int (*x)[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
}
And call it as
int arr[n][n];
new_array(&arr);
You can pass around arbitrarily dimensions arrays like any another variable if you wrap them up in a struct:
#include <stdio.h>
#define n 3
struct S {
int a[n][n];
};
static struct S make_s(void)
{
struct S s;
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
s.a[i][j] = i + j;
}
return s;
}
static void print_s(struct S s)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf(" %d", s.a[i][j]);
printf("\n");
}
}
int main(void) {
struct S s;
s = make_s();
print_s(s);
return 0;
}
You are probably declaring n as a constant integer:
const int n = 3;
Instead, you should define n as a preprocessor definition:
#define n 3

Resources