casting void** to 2D array of int - C - c

i am trying to cast a void** pointer to an int** 2D array in C
here is the code that i am trying to work with (with all the extraneous bits removed):
\*assume that i have a data structure called graph with some
*element "void** graph" in it and some element "int order" */
void initialise_graph_data(graph_t *graph)
{
void **graph_data = NULL;
int (*matrix)[graph->order];
size_t size = (graph->order * graph->order) * sizeof(int);
graph_data = safe_malloc(size); /*safe malloc works fine*/
matrix = (int(*)[graph->order])graph_data;
graph->graph = graph_data;
}
when i compile that, it works fine, but gives me a warning that variable 'matrix' is set but not used. i dont really want to have to use the interim matrix variable because the function is just supposed to initialise the array, not put anything in it; but if i try to cast graph_data directly to an int** when i am assiging it to graph->graph like so:
graph->graph = (int(*)[graph->order])graph_data;
it gives me an assignment from incompatible pointer type warning.
am i just not casting it properly? does anyone have any suggestions as to how i can make it work without the interim "matrix" variable? or if not, what i can do with that variable so that it doesnt give me the warning that it is set but not used?
thanks

The compiler is right, an array of arrays (or a pointer to an array) is not the same as a pointer to a pointer. Just think about how they would be laid out in memory:
A matrix of size MxN in the form of an array of arrays:
+--------------+--------------+-----+----------------+--------------+-----+------------------+
| matrix[0][0] | matrix[0][1] | ... | matrix[0][N-1] | matrix[1][0] | ... | matrix[M-1][N-1] |
+--------------+--------------+-----+----------------+--------------+-----+------------------+
A and the same "matrix" in the form of pointer to pointer:
+-----------+-----------+-----------+-----+
| matrix[0] | matrix[1] | matrix[2] | ... |
+-----------+-----------+-----------+-----+
| | |
| | V
| | +--------------+--------------+-----+
| | | matrix[2][0] | matrix[2][1] | ... |
| | +--------------+--------------+-----+
| |
| V
| +--------------+--------------+-----+
| | matrix[1][0] | matrix[1][1] | ... |
| +--------------+--------------+-----+
|
V
+--------------+--------------+-----+
| matrix[0][0] | matrix[0][1] | ... |
+--------------+--------------+-----+
It doesn't matter if you allocate the correct size, the two variables simply are incompatible which is what your compiler is telling you.

Related

How to realloc 2d struct pointer with different size

I want to realloc 2d pointer array. It must be dynamic as follows ascii
+=====+==============+==============+==============+==============+======+
| | [0] | [1] | [2] | [3] | [..] |
+=====+==============+==============+==============+==============+======+
| [0] | 'a' | 'b' | 'c' | 'd' | |
+-----+--------------+--------------+--------------+--------------+------+
| [1] | object[0][0] | object[1][0] | object[2][0] | object[3][0] | |
+-----+--------------+--------------+--------------+--------------+------+
| [2] | object[0][1] | object[1][1] | object[2][1] | object[3][1] | |
+-----+--------------+--------------+--------------+--------------+------+
| [3] | object[0][2] | object[1][2] | object[2][2] | | |
+-----+--------------+--------------+--------------+--------------+------+
| [4] | object[0][3] | | object[2][3] | | |
+-----+--------------+--------------+--------------+--------------+------+
| [5] | object[0][4] | | | | |
+-----+--------------+--------------+--------------+--------------+------+
| [6] | object[0][5] | | | | |
+-----+--------------+--------------+--------------+--------------+------+
In this table every cols size is different. How can i do this with 2d struct. I allocated matrix with malloc. But i want to realloc second index. Like this matrix[25][n]. N must be realloc for every column with different size. But it must be on runtime
Code :
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char word[20];
}Dictionary;
Dictionary **object;
void initializeDictionary()
{
// Create matrix [29][1]
object=(Dictionary**)malloc(29 * sizeof(Dictionary*));
object[0]=(Dictionary*)malloc(1*sizeof(Dictionary));
}
With pointers this comes naturally. In your code you have a Dictionary** which indeed is a pointer to pointer to Dictionary. But you can see it an array of Dictionary* in which each pointer points to a different sized array of Dictionary objects.
Dictionary** objects;
const int COLUMNS = 29;
objects = malloc(COLUMNS * sizeof(Dictionary*));
objects[0] = malloc(2 * sizeof(Dictionary)); // first column 2 elements
objects[1] = malloc(3 * sizeof(Dictionary)); // second column 3 elements
// ...
for (int i = 0; i < COLUMNS; ++i)
free(objects[i]);
free(objects);

C, Multidimensional arrays: array whose elements are one-dimensional arrays?

Does this statement make sense, from the book C Programming: A Modern Approach, 2nd Edition on page 269
Just as the name of a one-dimensional array can be used as a pointer, so can the name of any array, regardless of how many dimensions it has. Some care is required, though. Consider the following array:
int a[NUM_ROWS][NUM_COLS];
a is not a pointer to a[0][0]; instead, it's a pointer to a[0]. This makes more sense if we look at it from the standpoint of C, which regards a not as a two-dimensional array but as a one-dimensional array whose elements are one-dimensional arrays. When used as a pointer, a has type int (*) [NUM_COLS] (pointer to an integer array of length NUM_COLS).
I'm confused because when I think "array whose elements are one-dimensional arrays" I think a jagged-array, but that's not what's going on here.. This is more like a macro with pointer arithmetic?
Is this in reference to the type system and how it treats multidimensional arrays? Could any one explain this?
Yes, it makes sense, and no, it's not even talking about "ragged" or "jagged" arrays. It's simply that when we say
int a[NUM_ROWS][NUM_COLS];
what we're creating is an array a, and what it's an array of is... other arrays. You could think of it like this:
+---------------------------------------+
| +--------+--------+--------+--------+ |
a: [0]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[1]: | | | | | | |
| +--------+--------+--------+--------+ |
+ +
| +--------+--------+--------+--------+ |
[2]: | | | | | | |
| +--------+--------+--------+--------+ |
+---------------------------------------+
(Here NUM_COLS is evidently 4, and NUM_ROWS is 3.)
A two- (or more) dimensional array is 100% analogous to a simple, single-dimensional array -- you just have to be careful thinking about the analogies. If a is an array, then any mention of a in an expression where its value is needed results in a pointer to the array's first element, &a[0]. So given the two-dimensional array a we're talking about, a's value is &a[0] and is a pointer to an array of NUM_COLS integers.
It has to work this way, if multidimensional array subscripts are to work correctly. If we write a[i][j], that's interpreted as (a[i])[j]. a turns into a pointer to the array's first element, as usual, but a[i] is equivalent to *(a + i), where the pointer arithmetic ends up being scaled by the size of the pointed-to element -- that is, under the hood, it's more like *(a+ i * sizeof(*a)). So sizeof(*a) has to be sizeof(int [NUM_COLS]), or NUM_COLS * sizeof(int). That way a[i] gets you the i'th subarray, and then j can select one of the cells -- the int-sized cells -- of the subarray.
One final note: I've talked colloquially about "multi-dimensional arrays", but strictly speaking, and as many of the regulars here are fond of pointing out, C has no multidimensional arrays; it has only single-dimensional arrays, and what we think of as a two-dimensional array is actually, as we've seen here, a single-dimensional array whose elements happen to be other single-dimensional arrays. (If C had true multi-dimensional arrays, the subscripts would probably look like a[i,j] instead of a[i][j].)
Addendum: Despite your mention of pointer arithmetic, and my mention of pointer arithmetic, it's important to realize that there are no pointers involved in a's definition. Pointers arise only when we try to "take the value of" a, or explain how a[i] is equivalent to *(a + i).
For a data structure that does involve pointers, we could contrast the situation described by the code
int *a2[NUM_ROWS];
for(i = 0; i < NUM_ROWS; i++)
a2[i] = malloc(NUM_COLS * sizeof(int));
This gives us a very different memory layout:
+-----+
a2: | | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
And this is what's usually called a "ragged" or "jagged" array, since it's obviously not necessary that all the rows in this case be the same length. Nevertheless, almost magically, the cells in the "ragged" array can also be accessed using the a2[i][j] notation. And for full dynamism, we could use
int **a3 = malloc(NUM_ROWS * sizeof(int *));
for(i = 0; i < NUM_ROWS; i++)
a3[i] = malloc(NUM_COLS * sizeof(int));
resulting in this memory layout:
+-----+
a3: | |
| * |
| | |
+--|--+
|
|
V
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
| | +--------+--------+--------+--------+
| *------->| | | | |
| | +--------+--------+--------+--------+
+-----+
And a3[i][j] works here, too.
(Of course, in real code constructing "dynamic arrays" like a2 and a3, we'd have to check to make sure that malloc didn't return NULL.)
Another way to look at it...
For any type T, we create an array as
T arr[N];
where T can be int, char, double, struct foo, whatever, and reads as “N-element array of T”. It can also be another array type. So, instead of just int, suppose T is an M-element array of int, which we’d write as
int arr[N][M];
This reads as “arr is an N-element array of M-element arrays of int”. This isn’t a jagged array - all the “rows” are the same size. But it’s not exactly a 2-dimensional array, either - it is an array of arrays. The expression arr[i] has an array type (int [M]).
This view helps us figure out pointer to array types as well. Except when it is the operand of the sizeof or unary & operator, or is a string literal used to initialize a character array in a declaration, an expression of type “N-element array of T” (T [N]) will be converted (“decay”) to an expression of type “pointer to T” (T *). Again, if you replace T with an array type int [M], then you have an expression of type “N-element array of M-element arrays of int” (int [N][M]), which “decays” to type “pointer to M-element array of int” (int (*)[M]).

How memory is allocated when we use malloc to create 2-dimensional array?

I want to create an integer array[5][10] using malloc(). The difference between memory address of array[0] and array[1] is showing 8. Why?
#include <stdio.h>
#include <stdlib.h>
int main() {
int *b[5];
for (int loop = 0; loop < 5; loop++)
b[loop] = (int*)malloc(10 * sizeof(int));
printf("b=%u \n", b);
printf("(b+1)=%u \n", (b + 1));
printf("(b+2)=%u \n", (b + 2));
}
The output is:
b=2151122304
(b+1)=2151122312
(b+2)=2151122320
The difference between memory address of array[0] and array[1] is showing 8. Why?
That's because sizeof of a pointer on your platform is 8.
BTW, use of %u to print a pointer leads to undefined behavior. Use %p instead.
printf("(b+1)=%p \n",(b+1));
printf("(b+2)=%p \n",(b+2));
Difference between array of pointers and a 2D array
When you use:
int *b[5];
The memory used for b is:
&b[0] &b[1] &b[2]
| | |
v v v
+--------+--------+--------+
| b[0] | b[1] | b[2] |
+--------+--------+--------+
(b+1) is the same as &b[1]
(b+2) is the same as &b[2]
Hence, the difference between (b+2) and (b+1) is the size of a pointer.
When you use:
int b[5][10];
The memory used for b is:
&b[0][0] &b[1][0] &b[2][0]
| | |
v v v
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ ...
| | | | | | | | | | | | | | | | | | | | | ...
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ ...
(b+1) is the same as &b[1], The value of that pointer is the same as the value of &b[1][0] even though they are pointers to different types.
(b+2) is the same as &b[2], The value of that pointer is the same as the value of &b[2][0]
Hence, the difference between (b+2) and (b+1) is the size of 10 ints.
First, with int *b[5] you are not creating a two dimensional array, but an array of pointers.
The elements of the array b are pointers. Each occupies the size of a pointer, which depends on your architecture. In a 64-bits architecture it will probably occupy 64 bits (8 bytes). You can check that by printing sizeof(int*) or sizeof(b[0])
Memory allocation will look like
b
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[0]+--------------> | | | | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[1]+--------------> | | |....... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[2]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[3]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
| | +------+------+-----------+-----+-----+-----+-----+
| b[4]+--------------> | | | ...... | | | | |
| | +------+------+-----------+-----+-----+-----+-----+
+-----+
b will point to b[0], after decay, and b + 1 will give the address of b[1]. Size of pointer on your machine is 8 bytes, therefore you are getting a difference of 8 in the address.
Beside of this
Do not cast return value of malloc
b[loop]=malloc(10*sizeof(int));
and use %p for pointer data type
printf("b=%p \n",(void *)b);
printf("(b+1)=%p \n",(void *)(b+1));
printf("(b+2)=%p \n",(void *)(b+2));
What you've declared is not technically a two dimensional array but an array of pointers to int, each of which points to an array of int. The reason array[0] and array[1] are 8 bytes apart is because you have an array of pointers, and pointers on your system are 8 bytes.
When you allocate each individual 1 dimensional array, they don't necessarily exist next to each other in memory. If on the other hand you declared int b[5][10], you would have 10 * 5 = 50 contiguous integers arranged in 5 rows of 10.

Association for type declaration statements in C

How are type declaration statements in C parsed (Right to Left or Left to Right)?
eg: consider the statement:
const char* const arr="hello";
How exactly is the above statement parsed?
Dear All, To those who found it difficult to understand my question:
In the above declaration statement arr is a variable. When the above statement is read by the compiler (which happens to parse the line) is arr considered a constant variable and then categorised as a character pointer or is it first recognised as a character pointer and then concluded with a constant value.
The doubt is due to the following thought:
If only const were to be declared ex: const int x; then the compiler does things behind the scene to make it a constant, and If I were to declare only a pointer ex: int* x; again compiler does things behind the scenes to categorise x as a pointer variable to distinguish it from just another integer variable. But in case the declaration is something like:
const int* const x; the behind the scenes action has to happen in some order so as x is recognised as and integer pointer variable and a const variable and then that has a constant value.
I would also be glad to hear the "behind the scenes" actions that C compiler does to separate between int variable char vaiable... pointer variable, register variable, In all how does a compiler recognise the difference.
Finally thanks for your patience to read such a long question.
Declarations aren't parsed strictly left to right or right to left. C declaration syntax is somewhat complicated.
Based on the grammar found in the online C2011 standard, section 6.7, your example parses out like so (skipping a few steps for brevity):
char const * const arr = "hello" ;
-+-- --+-- ^ --+-- -+- ^ ---+--- ^
| | | | | | | |
type type | type direct | initializer |
specifier qualifier | qualifier declarator | | |
| | | list | | | |
| | | | | | | |
| | +--+---+ | | | |
| | | | | | |
| | pointer | | | |
| | | | | | |
| | +------+------+ | | |
| | | | | |
| | declarator | | |
| | | | | |
| | +---------+----+-------+ |
| | | |
| | | |
| | | |
+---+----+ | |
| | |
declaration init-declarator-list |
specifiers | |
| | |
+-------------------------+-------+------------------------+
|
declaration
So, something to note about the pointer part of the declaration; the const following the * is part of the pointer non-terminal. That part of the grammar looks like this:
pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer
When you write T * const p, that means you are declaring p as a constant pointer; you will not be able to assign a different value to p (you can't make it point to a different object).
This also means you can declare an object like T * const * const p, or T * const restrict * volatile * p;. In each case, the list of type qualifiers is associated with the * appearing to their left.
The way to read hairy declarations is to start with the left-most identifier and work your way out, remembering the following rules:
*a[] - a is an array of pointer
(*a)[] - a is a pointer to an array
*f() - f is a function returning a pointer
(*f)() - f is a pointer to a function
* qual p - p is a qualified pointer
qual * p - p is a pointer to qualified type
where qualified may be one of const, volatile, restrict, or _Atomic. In the case of function declarations, you'll be applying these rules recursively to each function parameter.
So,
arr -- arr
* const arr -- is a const pointer to
char const * const arr -- const char
char const * const arr = "hello"; -- initialized to "hello"
This could also be written
const char * const arr = "hello";
and it will mean the same thing. The reason for this is that the declaration-specifiers non-terminal (which, in this case, covers the part of the declaration to the left of the *) is defined as
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
This syntax means you can have any one of a storage-class-specifier, a type-specifier, a type-qualifier, a function-specifier, or an alignment-specifier followed by zero or more additional such items (subject to certain constraints). This is how you can get declarations like
static unsigned long int x;
which parses as
static unsigned long int x ;
--+--- ----+--- --+- -+- ^ ^
| | | | | |
storage type type type direct |
class specifier specifier specifier declarator |
specifier | | | | |
| | | declaration | |
| | | specifiers | |
| | | | | |
| | +-----+----+ | |
| | | | |
| | declaration init |
| | specifiers declarator |
| | | | |
| +---------+---------+ | |
| | | |
| declaration | |
| specifiers | |
| | | |
+-----------+-------------+ init |
| declarator |
declaration-specifiers list |
| | |
+----------------------+----------------+--------+
|
declaration
The order in which static, unsigned, long, and int appear doesn't matter (although people will probably hit you if you write int long static unsigned x). Your declaration must include at least one type-specifier, and you can't write things like float char double x or double double double double y, but those rules are enforced at a different level.
In C, variables are declared the way you use them, e.g.
int * t[12];
means than *t[somevalue] is an int.
Back to your example :
const char *arr = "hello";
means you cannot change the chars inside the string
arr[0] = 'x' is forbidden
arr = "xyz" is allowed
char * const arr = "hello";
means you cannot change the value of the pointer arr
arr[0] = 'x' is allowed
arr = "xyz" is forbidden

managing a collection of structs in c

I am learning c, and have come across an issue storing and managing structs; let me explain.
I am quite familiar with Java, and I am starting to understand how to properly use pointers and references in c. My goal is to make and store hundreds of stuct:
struct creature{
int id;
char name[12];
}
In java, I am able to create an Array like:
creature c [];
and then store and manipulate objects inside that array. I want the same effect in c using a struct "creature".
My first attempt was:
creature *creatures = malloc(sizeof(creature));
I am not entirely sure what that even does. My goal was to create a block of memory that strictly held struct pointers, like the Java array.
from here, I want to create new creature structs, and store their pointers in the creatures variable, that has memory allocated from using malloc.
I hope this was enough information to explain my problem.
Thanks!
Right, so what you want is an array of pointers. Note that in Java, whenever you have something like:
String s = ...;
This translates to a pointer in c:
String *s = ...;
Let's take the easy case first of a fixed-size array of pointers. This is simply:
creature *creatures[10];
for (var i=0; i < 10; i++) {
creatures[i] = malloc(sizeof(creature));
}
Now you have an array of pointers to creatures, each malloced separately. But, if you don't know how big your array of creatures should be, then you have to malloc the array of creatures. Note that if you have, say, a malloced int array, you'd do the following:
int *ints = malloc(sizeof(int) * 10);
ints[0]; ints[1]; //etc...
That is, an array is represented as a pointer to the first element. What you want now is an array of pointers, which ends up being a pointer to a pointer:
var numCritters = 10;
creature **creatures = malloc(sizeof(creature *) * numCritters);
for (var i=0; i < numCritters; numCritters++) {
creatures[i] = malloc(sizeof(creature));
}
The first malloc creates a pointer to an array of creature * pointers. Note we use sizeof(creature *) here, not sizeof(creature), because the array is of pointers, not of creatures.
Each of the next mallocs then creates a pointer to a creature, same as in the case of a fixed-size array.
Be sure to have a free for each malloc - that is, one for each creature * and one for the creature **.
Note that this is different from what Pankrates suggested. Which solution you want to use depends on what you want to do. His creates a big block of creatures:
creature *creatures = +--------------------+
| |
| |
| Creature 0 |
| |
| |
+--------------------+
| |
| |
| Creature 1 |
| |
| |
+--------------------+
| |
| |
| Creature 2 |
| |
| |
+--------------------+
| ... |
Whereas mine creates an array of pointers, each one pointing to a creature:
+--------------------+
| |
creature *creatures = +------+ | |
| ptr0 | ----> | Creature 0 |
+--------------------+ +------+ | |
| | +-- | ptr1 | | |
| | | +------+ +--------------------+
| Creature 1 | <-+ | ptr2 | --+
| | +------+ | +--------------------+
| | | .... | | | |
+--------------------+ | | |
+-> | Creature 2 |
| |
| |
+--------------------+
You are almost there. malloc takes the number of bytes that you want to allocate as an argument, therefore you need to multiply the size of the struct times the number of structs that you want to allocate:
int number_of_creatures = 10;
creature *creatures = malloc(sizeof(creature) * number_of_creatures);
You should also always check the returned pointer from malloc() to check if the allocation was successful
if (creatures == NULL)
printf("Allocating memory failed!\n");

Resources