# Thread: How Do I Send a Two-Dimensional Char Array to a Function?

1. ## How Do I Send a Two-Dimensional Char Array to a Function?

My compiler's griping at me when I try to compile the following code:

Code:
```#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <combination.h>
#include <limits.h>		/* for CHAR_BIT */

#define MAX 44
#define BITMASK(b) (1 << ((b) % CHAR_BIT))
#define BITSLOT(b) ((b) / CHAR_BIT)
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a, b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
#define BITNSLOTS(nb) ((nb + CHAR_BIT - 1) / CHAR_BIT)

void increment(char* bitarray, int n);
int test_all_zero(char* bitarray, int n);
void one_diag(char** bitarray, int i, int j);
void make_matrix(char** bitarray, char* U_array, int n);
void invert(char* bitarray, int n);
void display(char** bitarray, int n);

main(){
char bitarray[MAX][BITNSLOTS(MAX)];
int i,j;
for (i=0; i<MAX; i++){
memset(bitarray[i], 0, BITNSLOTS(MAX));
}

char U_array[BITNSLOTS(MAX*(MAX-1)/2)];
memset(U_array, 0, BITNSLOTS(MAX*(MAX-1)/2));

/* TEST CODE START */
char test_array[BITNSLOTS(45)];
memset(test_array, 0, BITNSLOTS(45));

char test_matrix[10][BITNSLOTS(10)];
for (i=0; i<10; i++){
memset(test_matrix[i], 0, BITNSLOTS(10));
}

printf("Starting:\n");
make_matrix(test_matrix, test_array, 10);
display(test_matrix, 10);

printf("Inverting:\n");

while (test_all_zero(test_array, 45)){
invert(test_array, 45);
}

make_matrix(test_matrix, test_array, 10);
display(test_matrix, 10);

/* TEST CODE END */

getch();
}

void increment(char* bitarray, int n){
int i = 0;
while (i < n){
if (!BITTEST(bitarray, i)){
BITSET(bitarray, i);
i = n;
}
else{
BITCLEAR(bitarray, i);
i++;
}
}
}

int test_all_zero(char* bitarray, int n){
int i;
int counter = 0;
for (i=0; i<n; i++){
if (!BITTEST(bitarray, i)){
counter++;
}
}
if (counter == n){
return 1;
}
else{
return 0;
}
}

void one_diag(char** bitarray, int i, int j){
if (i == j){
BITSET(bitarray[i], j);
}
}

void invert(char* bitarray, int n){
int i;
for (i=0; i<n; i++){
if (BITTEST(bitarray, i)){
BITCLEAR(bitarray, i);
}
else{
BITSET(bitarray, i);
}
}
}

void make_matrix(char** bitarray, char* U_array, int n){
int i,j,k;
for (i=0,j=i+1,k=0; k<n; j++,k++){
if (j > n){
i++;
j = i+1;
}
if (BITTEST(U_array, k)){
BITSET(bitarray[i], j);
BITSET(bitarray[j], i);
}
else{
BITCLEAR(bitarray[i], j);
BITCLEAR(bitarray[j], i);
}
}
}

void display(char** bitarray, int n){
int i, j;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
if (BITTEST(bitarray[i], j)){
printf("1");
}
else{
printf("0");
}
}
printf("\n");
}
printf("\n");
}```
It's giving me:

[Warning] passing arg 1 of 'make_matrix' from incompatible pointer type
[Warning] passing arg 1 of 'display' from incompatible pointer type
...

And so on. I've looked all over for good examples of how to pass a two-dimensional character array to a function, and none of the methods have worked. Can anyone help me please?

2. If you want to pass a multi-dimensional array to a function, the simplest way is to specify all of the array sizes except the leftmost; e.g.,
Code:
```int one[10];
int two[10][20];
int three[10][20][30];

void func_one(char one[]) {}
void func_two(char two[][20]) {}
void func_three(char three[][20][30]) {}

func_one(one);
func_two(two);
func_three(three);```
Note that the syntax "char three[][20][30]" is equivalent to "char (*three)[20][30]". I prefer the latter, although I imagine you'd likely find the former easier to read. Note that "char *three[20][30]" is different; that indicates a two dimensional array whose elements are of type char*.

3. In main() test_matrix is the first argument to both make_matrix() and display(). It's a pointer to BITNSLOTS(10) chars taken as a unit but the function defn declares it to be a char** pointer and that's why the compiler warnings.

4. Originally Posted by itCbitC
In main() test_matrix is the first argument to both make_matrix() and display(). It's a pointer to BITNSLOTS(10) chars taken as a unit but the function defn declares it to be a char** pointer and that's why the compiler warnings.
All right... how do I rectify this?

5.  Here I am rambling on in general, without paying attention to your problem.

You could try passing "char [][BITNSLOTS(MAX)]" parameters to your functions instead of "char **" parameters.
[/edit]

You can't just use a char** because the compiler doesn't know how many elements are between array[0][0] and array[1][0]. It needs this information to figure out what you mean when you address the elements in the array. Hence my examples above where you tell the compiler how many elements there are in dimensions besides the leftmost one. (The compiler doesn't need to know how many elements are in the leftmost array dimension, because it doesn't do array bounds checking . . . .)

Anyway. If you want to pass a 2D array of any dimensions to a function, I suppose you could flatten the array like this.
Code:
```#include <stdio.h>

void func(int *array, int x_size, int y_size);

int main() {
int data[][3] = {
{1, 2, 3},
{4, 5, 6}
};

/* Now data[0][0] = 1
[0][1] = 2
[0][2] = 3
[1][0] = 4
...
*/

/* x_size: number of elements in data[x][*] */
/* y_size: number of elements in data[*][y] */
size_t x_size = sizeof(data) / sizeof(data[0]);  /* this will be 2 */
size_t y_size = sizeof(data[0]) / sizeof(data[0][0]);  /* this will be 3 */

func((int *)data, x_size, y_size);

return 0;
}

void func(int *array, int x_size, int y_size) {
int x, y;

for(y = 0; y < y_size; y ++) {
for(x = 0; x < x_size; x ++) {
printf("%d", *(array + (x * y_size) + y));
if(x + 1 < x_size) putchar(' ');
}
putchar('\n');
}
}```
That's a pretty bad way to do it, though. (And my names are horrible, but never mind that . . . .) And I'm sure you could get away with a int** pointer instead of a int* pointer with some more casting, which might be marginally more intuitive. Plus there may be other ways I'm not aware of.

Personally, if I'm passing a two-dimensional array to a function, I wrap it in a structure. This has several advantages: you're already passing the size of the array to the function, because presumably it is in the structure, and you don't have to do any casting . . . if you create a new level of structure indirection for each dimension of the array, that is. For example:
Code:
```struct list_t {
struct name_t *name;
size_t names;
};

struct name_t {
char *name;
size_t length;
};```

6. Originally Posted by DonFord81
All right... how do I rectify this?
There are many ways it can be written depending on what the macro BITNSLOT(10) evaluates to. If BITNSLOT(10) evaluates to 2 then:
Code:
```char (*pa) [2]
char pa[][2]```
Edit:: that was just an example so the parameterized decl can be written as:
Code:
```char (*pa) [BITSNSLOT(10)]
char pa[][BITSNSLOT(10)]```

7. It worked! Thank you all so much!

8. It's better to merely "flatten" it to a 1D array by taking a T* instead of T** if you don't want to pass it as a 2D array since all arrays are just laid out after each other in memory.
So there you go.