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

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    38

    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. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    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*.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    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. #4
    Registered User
    Join Date
    Nov 2008
    Posts
    38
    Quote Originally Posted by itCbitC View Post
    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. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    [edit] 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;
    };
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by DonFord81 View Post
    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)]
    Last edited by itCbitC; 02-25-2009 at 05:43 PM.

  7. #7
    Registered User
    Join Date
    Nov 2008
    Posts
    38
    It worked! Thank you all so much!

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  3. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM

Tags for this Thread