Create a d-dimensional pointer [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
We use to indicate a pointer with the symbol *. Iterating the procedure, we obtain a "double" pointer **, a "triple" pointer *** and, more generally, a "d-dimensional" pointer (for each d positive natural number).
Problem: given such a d as an input, define S to be a d-dimensional pointer.
Because I started studying dynamic structures only some days ago, I am unfortunately a bit in trouble with this problem.
Does anyone have a suggestion/hint?
Thank you in advance, and my apologies for my probably too basic question.
Ps: I used the word "pointer" without specify its type only for sake of brevity.

This problem has a solution in C as long as two conditions are met:
The value of d is known at compile time, and
d has a pre-defined limit, e.g. 10
You can solve this problem by defining a series of macros and "pasting" the value of d as a token:
#define D_PTR(d,T) D_PTR##d(T)
#define D_PTR0(T) T
#define D_PTR1(T) T*
#define D_PTR2(T) T**
#define D_PTR3(T) T***
...
#define D_PTR10(T) T**********
Now you can declare d-dimension pointers like this:
D_PTR(5,int) ptr5 = NULL;
Demo.

There are three distinct ways to solve this:
Your d is a compile-time constant. For this case, dasblinkenlight has already given the solution.
The hacky-C solution: Just use a cast to get back to the pointer type:
double* dereferenceDLevels(double* pointer, int d) {
for(; d--; ) pointer = *(double**)pointer;
return pointer;
}
I do not recommend this approach, though. It's just too dirty.
You implement your d-level pointers as user defined types:
typedef struct nLevelPointer {
int n;
union {
nLevelPointer* pointer;
double value;
};
} nLevelPointer;
double nLevelPointer_dereference(nLevelPointer* me) {
for(int i = me->n; i--; ) me = me->pointer;
return me->value;
}
I consider this approach the cleanest and most flexible one. However, it has the trade-off of requiring a significant amount of boilerplate code to make it fly.

Basically the number of * represents the number of indirections to reach the variable. So you have to create d indirections. I assume this has no practical application - that's an answer to a recreative problem.
An indirection in C is an address, a pointer. Creating d indirections means the creation of d addresses to reach a variable data (the space allocated to the variable of type T).
p(d) -> p(d-1) -> ... -> p(1) -> variable
To create dynamically such a structure, you could do it via malloc (replace T with any known type), and - since you may not specify the number of * dynamically to a pointer - requires some C hacking.
So, again, this is not something recommended and is a particularly bad design, especially for inexperienced C developers. Purpose is to show it could be done dynamically, whatever the value of d.
Say T is a double
int d = ...; // from input (d >= 1)
double variable;
double **S = malloc(sizeof(double *) * d); // array of pointers to pointer
S[d-1] = &variable; // last address points to target
int i;
for(i=d-2 ; i>=0 ; i--) S[i] = (double *)&S[i+1]; // previous address
// points to next location
There is no way to represent an arbitrary number of indirections in C, so S is only a ** to satisfy the compiler requirements, and is cast when necessary.
Let's try with d set to 4 and applying the algorithm above (say T is a double), having
double variable is at address 0100 (decimal), value 3.14
S address given by malloc at 1000
a pointer size being 4
a double size being 8
variable
v
[8 bytes double value 3.14]
^
0100
S
v
[1004][1008][1012][0100]
^ ^
1000 1012
Now the structure is in place, how to use/test it? You could create a function that returns the type T (double here), take the S value and d, operate the d indirections and return the variable
double getvariable(double **S, int d) {
while (--d > 0) S = (double **)*S; // d-1 iterations
return *(double *)*S;
}
trying it
printf("%lf\n", getvariable(S, d)); // 3.14
to test the above structure without a function, for d == 4, you could create
double ****p = (double ****)*S;
printf("%lf\n", ****p); // 3.14

Problem: given such a d as an input, define S to be a d-dimensional
pointer.
It's possible in C to functionally represent an N dimensional array at run time, if not a pointer with an arbitrary number of levels of indirection. This could be a start (uncompiled, and this utterly ignores any possible alignment issues):
void *allocateArray( unsigned int N, size_t elemSize, unsigned int *dimensions )
{
if ( N == 1U )
{
return( malloc( elemSize * dimensions[ 0 ] ) )
}
void *array = malloc( sizeof( void * ) * dimensions[ 0 ] );
for ( unsigned ii = 0; ii < dimensions[ 0 ]; ii++ )
{
array[ ii ] = allocateArray( N - 1, elemSize, &( dimensions[ 1 ] ) );
}
return( array );
}
Note, that is not a very efficient way of allocating an N-dimensional array.
You could call it like this:
unsigned dims[] = { 5,7,8,9 };
unsigned d = sizeof( dims ) / sizeof( dims[ 0 ] );
size_t elemSize = sizeof( double );
void *array = allocateArray( d, elemSize, dims );
A varargs solution is probably possible, too.
Dereferencing the array would require something similar. This returns the address of the element dereferenced:
void *dereferenceArray( void *array, unsigned int N,
size_t elemSize, unsigned int *element )
{
if ( N == 1U )
{
char *tmp = array;
return( tmp + ( elemSize * element[ 0 ] ) );
}
else
{
void **tmp = array;
return( dereferenceArray( tmp[ element[ 0 ] ],
N - 1, elemSize, &( element[ 1 ] ) ) );
}
}
It'd be much easier in C++ as you could provide a [] operator to your array object and nest them to build N-dimensional arrays.

You could create the runtime equivalent of a d-indirection pointer by chaining as many void ** pointers as you need. A sparse array could then be built this way:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
printf("Call this passing d (dimensions), n (elements for each dim), u (used elements) as parameters\n");
return 0;
}
int d = atoi(argv[1]);
assert(d > 0);
int n = atoi(argv[2]);
assert(n > 0);
int u = atoi(argv[3]);
assert(u < n * d);
// Creating
void *root = malloc(sizeof(void *) * n);
memset(root, 0, sizeof(void *) * n);
srand(time(NULL));
int i, p, c;
void **cursor;
for (int c = 0; c < u; ++c)
{
cursor = root;
for (i = 0; i < d; ++i)
{
p = rand() % n;
if (cursor[p] == NULL)
{
cursor[p] = malloc(sizeof(void *) * n);
memset(cursor[p], 0, sizeof(void *) * n);
}
cursor = cursor[p];
}
p = rand() % n;
if (cursor[p] == NULL)
cursor[p] = "Hello";
else
--c;
}
// Traversing
struct SE
{
void * *s;
int p;
};
struct SE *stack = malloc(sizeof(struct SE) * (d + 1));
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
}
else if (cursor[p] != NULL)
{
if (i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
else
{
printf("root");
for (c = 0; c < i; ++c)
printf("[%d]->", stack[c].p);
printf("[%d]=\"%s\"\n", p, cursor[p]);
}
}
}
// Tearing down
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
free(cursor[p]);
}
else if (cursor[p] != NULL && i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
}
free(root);
free(stack);
return 0;
}

Related

Global variable losing data in C?

I am trying to create a array of array of string where each row (if considered matrix) should have 3 strings of any length and a maximum of 10 rows
The data Structure is correct but I am very much surprised with the output I get in the global variable. So the matrix would act as the database to the program and hence kept in global space
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define MAX_NUM_ITEMS 10
#define MAX_ITEM_PER_ROW 3
static char *array[MAX_NUM_ITEMS][MAX_ITEM_PER_ROW];
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)
char *itoa_base(char *, int , int);
#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
char *itoa_base(char *s, int x, int base) {
s += ITOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
int x0 = x;
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
x /= base;
} while (x);
if (x0 < 0) {
*(--s) = '-';
}
}
return s;
}
int main(void)
{
int count = 0;
for (int i = 0; i < MAX_NUM_ITEMS; i++){
for (int j = 0; j < MAX_ITEM_PER_ROW; j++ ){
++count;
array[i][j] = TO_BASE(count, 16);
}
}
for (int i = 0; i < MAX_NUM_ITEMS; i++){
for (int j = 0; j < MAX_ITEM_PER_ROW; j++ ){
printf("%s ",array[i][j]);
}
printf("\n");
}
return 0;
}
From my logic I should see
1 2 3
4 5 6
7 8 9 and so on and not E E E
can't understand why that is happening
First, this:
(char [ITOA_BASE_N]){0}
Does not get you a new instance of a character array, unlike say golang. So, every time you call itoa(), you are calling it with the same character array. Somewhat worse, the character array is occupying a reclaimable stack address [ its scope is only that inner loop ], so it can be over written with random stuff shortly after. It is remarkably consistent though; I will give it that.
Changing the invocation to:
array[i][j] = strdup(TO_BASE(count, 16));
and adding a #include at the top produces the output you wanted.
If dynamic allocation is not permissible in your application, you will have to use a static allocation scheme, which you could make a bounded version of strdup like:
char *strnew(char *s) {
static char strspace[ITOA_BASE_N * MAX_NUM_ITEMS * MAX_ITEM_PER_ROW ];
static char *strnext = strspace;
if (strlen(s) + strspace >= &strspace[sizeof strspace]) {
s = "<error: out of space>"; /* something more clever is possible */
} else {
strcpy(strnext, s);
s = strnext;
strnext += strlen(strnext)+1;
}
return s;
}
which you could substitute for strdup. If you do the next person down the line a favour and use a more descriptive notion like MAX_STRING_SPACE which is based on the calculation; and rather than insert a "bad value", cause some sort of exception, I am sure they would appreciate it.
The problem is here:
itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
^^^^^^^^^^^^^^^^^^^^^^^
you are allocating a temp array (on the stack) which is only valid up to the end of the containing expression statement. So when the time comes to print them, the pointers you've stored in the matrix are dangling. What the compiler ends up doing is reusing the same memory for every call, so the strings end up overwriting.
You could instead use a static matrix of arrays rather than pointers:
static char array[MAX_NUM_ITEMS][MAX_ITEM_PER_ROW][ITOA_BASE_N];
then your call in the first loop becomes
itoa_base(array[i][j], count, 16);
you'll also need to "fix" itoa_base so it puts the result in the front of the array rather than the back. Obvious way is with a recursive loop like:
char *itoa_base(char *s, int x, int base) {
if (base >= 2 && base <= 36) {
if (x < 0) {
*s++ = '-';
x = -x; }
if (x >= base)
s = itoa_base(s, x/base, base);
*s++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[x % base];
}
*s = '\0';
return s;
}

Return two values with pop function from priority queue

I have priority queue which returns with pop function just int y, but I need return int x and int y. So I found, that I can use struct (struct point) to return two values from function, but I can't figure, how it implement (rewrite int out to struct and use it in main).
Structs:
typedef struct { int x; int y; int pri; } q_elem_t;
typedef struct { q_elem_t *buf; int n, alloc; } pri_queue_t, *pri_queue;
struct point{int PointX; int PointY;};
Pop function:
int priq_pop(pri_queue q, int *pri)
{
int out;
if (q->n == 1) return 0;
q_elem_t *b = q->buf;
out = b[1].y;
if (pri) *pri = b[1].pri;
/* pull last item to top, then down heap. */
--q->n;
int n = 1, m;
while ((m = n * 2) < q->n) {
if (m + 1 < q->n && b[m].pri > b[m + 1].pri) m++;
if (b[q->n].pri <= b[m].pri) break;
b[n] = b[m];
n = m;
}
b[n] = b[q->n];
if (q->n < q->alloc / 2 && q->n >= 16)
q->buf = realloc(q->buf, (q->alloc /= 2) * sizeof(b[0]));
return out;
}
Use in main():
/* pop them and print one by one */
int c;
while ((c = priq_pop(q, &p)))
printf("%d: %d\n", p, c);
I'm starting with C, so I will be gratefull for any help.
You can declare your structures like so:
typedef struct queue_element_struct { // It's good practice to name your structs
int x,y;
int pri;
} queue_element_t;
typedef struct priority_queue_struct {
queue_element_t *buf;
int n, alloc;
} pri_queue_t, *pri_queue; // Don't know what `*pri_queue` is for
Then change your function to return a pointer to a queue_element_t structure
queue_element_t * priq_pop(pri_queue q, int *pri)
Change
int out;
if (q->n == 1) return 0;
q_elem_t *b = q->buf;
out = b[1].y;
To
// Create new pointer to queue_element_t structure
// that will be returned by this function
queue_element_t *out;
out = (queue_element_t *) malloc(sizeof(queue_element_t));
if (! out) {
// Could not allocate
}
if (q->n == 1) return 0;
// Set data from queue
out->x = q->buf[1].x;
out->y = q->buf[1].y;
I don't know exactly what your function does, but that is how you return a structure in C.
You said you're just starting with C, so I recommend:
“Code Complete” book by Steve McConnell. It is very useful to comment your code (no matter how small)
properly name your variables: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Variable_Names
learn about pointers. All you can read about them, read it.
You could make your queue data of type struct point
Structs:
typedef struct point{int PointX; int PointY;} q_data;
typedef struct { q_data d; int pri; } q_elem_t;
typedef struct { q_elem_t *buf; int n, alloc; } pri_queue_t, *pri_queue;
Pop function:
q_data priq_pop(pri_queue q, int *pri)
{
q_data out = {0,0};
if (q->n == 1) return out;
q_elem_t *b = q->buf;
out = b[1].d;
if (pri) *pri = b[1].pri;
/* pull last item to top, then down heap. */
--q->n;
int n = 1, m;
while ((m = n * 2) < q->n) {
if (m + 1 < q->n && b[m].pri > b[m + 1].pri) m++;
if (b[q->n].pri <= b[m].pri) break;
b[n] = b[m];
n = m;
}
b[n] = b[q->n];
if (q->n < q->alloc / 2 && q->n >= 16)
q->buf = realloc(q->buf, (q->alloc /= 2) * sizeof(b[0]));
return out;
}
Use in main():
/* pop them and print one by one */
q_data c;
while ((c = priq_pop(q, &p)))
printf("%d: %d, %d\n", p, c.PointX, x.PointY);
Something like this should do the trick. I didn't test it though, so there might be errors.
good luck!
In C++ you would use a vector or something similar to store an array of Unfortunately you can't fall back on this.
Why not use an array though, you could have your queue be an array of q_elem_t?
q_elem_t *my_array = q_elem_t array[100]; //pseudo code
For more about making an array of structs see here: How do you make an array of structs in C?
The only thing with an array is that you need to either malloc an arbitrary size (i.e. array[100]) or you need to dynamically control the memory of the array. If you are starting out it might just be best to declare an array of size 100.
To me it looks like the confusion is in the lack of datastructure. Array is a good starting point but if you want to learn more check out linked lists and things like that.

Warning while sorting a 2D array with qsort

I'm trying to use qsort to sort a 2D array in C. The sort works, but I get the warning:
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]
How can I modify my compare function to eliminate the warning (given that qsort requires the parameters const void *pa, const void *pb ?
int cmp (const void *pa, const void *pb ) {
const int (*a)[2] = pa; // warning here
const int (*b)[2] = pb; // warning here
if ( (*a)[1] < (*b)[1] ) return 1;
if ( (*a)[1] > (*b)[1] ) return -1;
return 0;
}
I've read this post on Stack Overflow, but I'm still not sure how I should alter the compare function.
I have an array that looks like this:
int letterCount[26][2] = {{0, 0},{1, 0},{2, 0},{3, 0},{4, 0},{5, 0},{6, 0},{7, 0},{8, 0},{9, 0},{10, 0},{11, 0},{12, 0},{13, 0},{14, 0},{15, 0},{16, 0},{17, 0},{18, 0},{19, 0},{20, 0},{21, 0},{22, 0},{23, 0},{24, 0},{25, 0}};
Except in the second column, instead of zeroes, those are filled with other numbers. I'm trying to sort this 2d array by the second column, after 0s are filled in.
You could toy with the decls, but in the end I think this will suffice for the comparator you're using:
int cmp (const void *pa, const void *pb )
{
const int *a = pa;
const int *b = pb;
if (a[1] < b[1])
return -1;
return (b[1] < a[1]);
}
Your data "items" are nothing more than int[] offsets in a 2D array. Were this a pointer array rather than a genuine 2D array, this would be considerably different. Grijesh was very close to this, only missing the [1] offsets (and the simple math), and if he undeletes his answers to fix it I'll just drop this.
what is this supposed to do (*a)[2] ?
it appears that you're dereferencing a pointer to an array in a declaration.
here for a lack of better things to do I wrote my own version , I hope it'll help you :
#include <time.h>
#include <stdio.h>
void Qsort(int matrix[][2] , int lenght)
{
if(!lenght)
return;
int temp = 0 , pivot , b = 0 , e = lenght - 1 , test = 0;
const int MIN =0 , MAX = e;
srand(time(NULL));
test = (rand() % (MAX - MIN + 1)) + MIN;
pivot = matrix[test][1];
while(b < e)
{
while(matrix[b][1] < pivot)
b++;
while(matrix[e][1] > pivot)
e--;
temp = matrix[b][1];
matrix[b][1] = matrix[e][1];
matrix[e][1] = temp;
}
Qsort(matrix , b);
Qsort(&(matrix)[b + 1] , lenght - 1 - b);
}

problem by ordering a data structure using the qsort function in C

I need to order a array of data structure that contains information relating to a node origin, destination and weight. the problem is not ordered properly, because if two values ​​are equal to array.originNode simply takes the first value you get and not as it should be ordered.
This is how my code does order the structure
0 1 30
1 3 22
2 3 20
3 5 20
3 4 15
Process returned 0 (0x0) execution time : 0.015 s
Here's how it should order
0 1 30
1 3 22
2 3 20
3 4 15
3 5 20
I think the problem is the function that I am passing as parameter to qsort, which is not making the correct comparison. How do I change my comparison function to my code sorts the array of struct properly?
this is my full code
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
typedef struct dataNodes{
int originNode;
int destinationNode;
int weight;
struct dataNodes *next;
} ARRAYS;
int function (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main() {
ARRAYS array[6];
int n = 5, i;
array [0].originNode = 3;
array [1].originNode = 3;
array[2].originNode = 1;
array[3].originNode = 0;
array[4].originNode = 2;
array [0].destinationNode = 4 ;
array [1].destinationNode = 5;
array[2].destinationNode = 3;
array[3].destinationNode = 1;
array[4].destinationNode = 3;
array [0].weight = 15;
array [1].weight = 20;
array[2].weight = 22;
array[3].weight = 30;
array[4].weight = 20;
qsort(array,n,sizeof(array[0]),function);
for(i=0; i<n; i++)
{
printf("%d %d %d\n",array[i].originNode,array[i].destinationNode,
array[i].weight);
}
return 0;
}
You need to change your compare function to compare ARRAY records properly. First compare originNode, and if they're the same compare destinationNode.
int function (const void * a, const void * b)
{
const ARRAYS *ap = a;
const ARRAYS *bp = b;
if( ap->originNode < bp->originNode )
return -1;
else if( ap->originNode > bp->originNode )
return 1;
else if( ap->destinationNode < bp->destinationNode )
return -1;
else if( ap->destinationNode > bp->destinationNode )
return 1;
else
return 0;
}
You are sorting an array of (uh...) ARRAYS. So your sort function that you pass in should be comparing ARRAYS objects. Your code treats it as int's.
To do secondary sorting, you need to compare the corresponding secondary fields in the case that the primary fields are equal. Do the same for any more fields you want to compare.
So in your case, this sort function could work for you:
int sort_ARRAYS (const void * a, const void * b)
{
/* the arguments are pointers to ARRAYS objects */
const ARRAYS *x = a;
const ARRAYS *y = b;
int cmp;
/* primary */
cmp = x->originNode - y->originNode;
if (cmp != 0) return cmp;
/* secondary */
cmp = x->destinationNode - y->destinationNode;
if (cmp != 0) return cmp;
/* tertiary */
return x->weight - y->weight;
}
From the fine manual:
void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));
[...]
The compar argument is a pointer to the comparison function, which is called with two arguments that point to the elements being compared.
So your comparison function will receive two ARRAY * arguments disguised as const void * and your function just needs to cast them appropriately:
int
function(const void * a, const void * b) {
ARRAYS *aa = (ARRAYS *)a;
ARRAYS *bb = (ARRAYS *)b;
return aa->originNode - bb->originNode;
}
If you want a secondary sort key, then check if aa->originNode == bb->originNode and compare the secondary key if that's true; similarly for the tertiary key if needed.
Your current code is working by accident. This:
return ( *(int*)a - *(int*)b );
is actually comparing the first elements of the ARRAYS* arguments and it works because (a) there's no padding at the beginning of your structure and (b) originNode is at the beginning and it actually is an int.

Declaring a 2-dimensional array of unknown size, C

I have an array declared as a member of a struct in C. The array is declared as:
char mValue[MAXROWS][MAXCOLUMNS];
where MAXROWS and MAXROWS are 300. Is there a better way to do this? I mean, should I declare these as pointers instead?
Thanks!
As the previous poster suggested, a good way is to create a linear array and then "convert it to 2D". Many times, caching the 2D pointers greatly increases the speed of programs that use this array, like so:
mystruct *p = (mystruct*)calloc(ROWS * COLUMNS, sizeof(mystruct));
mystruct **p2 = (mystruct**)calloc(ROWS, sizeof(mystruct*));
for (int i = 0; i < ROWS; i++)
p2[i] = p + i*COLUMNS;
Then, you can simply access a 2D element with:
p2[row][column] = foo;
If all your rows are the same size, you should use a 1D array with the rows stored in sequence:
ABCDE
FGHIJ ---> ABCDEFGHIJKLMNO
KLMNO
The element at row i, column j will be at index i * ROW_LENGTH + j in the 1D array.
You can allocate the array using malloc(ROW_LENGTH * NUM_ROWS).
Another technique is to create a linear array and then convert it to 2d:
char *p = malloc(ROWS * COLUMNS);
// To access x, y
// This is in row-major ordr
*(p + (x * COLUMNS) + y);
I find that, for this kind of code, its better to create helper functions for accessing the elements. Depending on your profiling data, it may make sense to turn these into macros, but be extra careful.
#include <stdio.h> /* For printf */
/* This is the bit that would go in a header, like char2darray.h */
#include <stdlib.h> /* For calloc */
#include <assert.h> /* For assert */
struct Char2DArray
{
int rows;
int columns;
char *values;
};
/* This is the bit that would go in a source file, like char2darray.c */
void C2DA_initialize(struct Char2DArray *array, int rows, int columns)
{
assert(array != 0);
array->values = calloc(rows * columns, sizeof(char));
array->rows = rows;
array->columns = columns;
}
void C2DA_set(struct Char2DArray *array, int row, int column, int value)
{
assert(array != 0);
assert(array->values != 0);
assert(row < array->rows);
assert(row >= 0);
assert(column < array->columns);
assert(column >= 0);
array->values[(row * array->rows) + column] = value;
}
char C2DA_get(struct Char2DArray *array, int row, int column)
{
assert(array != 0);
assert(array->values != 0);
assert(row < array->rows);
assert(row >= 0);
assert(column < array->columns);
assert(column >= 0);
return array->values[(row * array->rows) + column];
}
void C2DA_free(struct Char2DArray *array)
{
free(array->values);
array->values = 0;
}
/* Here's a main.c to use it */
int main()
{
struct Char2DArray a;
C2DA_initialize(&a, 16, 16);
unsigned char c = 0;
int x, y;
for (x=0; x<16; x++) {
for (y=0; y<16; y++) {
C2DA_set(&a, x, y, (char)c);
c++;
}
}
printf("Character with hex value 0x55 is %c\n", C2DA_get(&a, 5, 5));
C2DA_free(&a);
return 0;
}
If the array needs to have a dynamic size, then you either need to make it a pointer or make the array the last member of the struct and play games when allocating the structure size.
Relevant comp.lang.c FAQ entries:
I came across some code that declared a structure like this...
How can I dynamically allocate a multidimensional array?
I found that changing my approach was very useful when faced with a similar problem.
A vector of vectors filled the same task, avoided memory allocation obstacles, and kept the same familiar shorthand. There may be other pitfalls, but I have not encountered them yet.
//Declaration of mValues, undefined size:
std::vector< std::vector<char> > mValues;
//Filling of mValues:
int max_x = 100 ;
int max_y = 100 ;
char char_foo = 'a';
for ( int x = 0; x <= max_x; ++x ) {
vector<char> temp;
for ( int y = 0; y <= max_y; ++y ) {
temp.push_back( char_foo );
}
mValues.push_back( temp );
}
// Referencing with familiar index notation:
mValues[a][b]; //The a-th row's b-th element
If you are struggling with arrays, but strongly desire the familiar indexing language, I have found this to be a good alternative.
Note that indexing order A then B is going to be critical for memory usage when recalling this data. Failure to call the information in an A,B order will be deeply problematic if performance is an issue.

Resources