initialising array of unknown size (newbie)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Adam Chapman

    initialising array of unknown size (newbie)

    Hi,

    Im trying to migrate from programming in Matlab over to C. Im trying
    to make a simple function to multiply one matrix by the other. I've
    realised that C can't determine the size of a 2d array, so im
    inputting the dimensions of those myself.

    The problem is that the output array (C=A*B) has as many rows as A and
    as many columns as B. I would think of initialising C with:

    double C[A_rows][B_cols];

    It looks like the compiler doesn't like this at all.

    What is the best way to define C? could i use a structure data type
    for A and B, or do the dimensions of C need to be defined using
    pointers? Perhaps the malloc function comes in somewhere.

    I would greatly appreciate any help.

    Thanks
    Adam
  • Ben Bacarisse

    #2
    Re: initialising array of unknown size (newbie)

    Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
    Im trying to migrate from programming in Matlab over to C. Im trying
    to make a simple function to multiply one matrix by the other. I've
    realised that C can't determine the size of a 2d array, so im
    inputting the dimensions of those myself.
    >
    The problem is that the output array (C=A*B) has as many rows as A and
    as many columns as B. I would think of initialising C with:
    >
    double C[A_rows][B_cols];
    >
    It looks like the compiler doesn't like this at all.
    There is nothing obviously wrong with the above. It would help to see
    the code or at least the error message. In particular, the "best"
    solution will be different if the dimensions are fixed and know at
    compile time, are fixed but known only at run time, or if they are
    true arbitrary variables. Also, are the dimensions small?
    What is the best way to define C? could i use a structure data type
    for A and B, or do the dimensions of C need to be defined using
    pointers? Perhaps the malloc function comes in somewhere.
    Maybe. It is important to know if you can use C99. C99 (the current
    standard) has some features that would make your task simpler. Rather
    the talk about both, it would be better to know what version of C you
    are using/obliged to use.

    Have you seen the comp.lang.c FAQ? http://c-faq.com/

    --
    Ben.

    Comment

    • Adam Chapman

      #3
      Re: initialising array of unknown size (newbie)

      On Oct 9, 11:57 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
      Adam Chapman <adam.chap...@s tudent.manchest er.ac.ukwrites:
      Im trying to migrate from programming in Matlab over to C. Im trying
      to make a simple function to multiply one matrix by the other. I've
      realised that C can't determine the size of a 2d array, so im
      inputting the dimensions of those myself.
      >
      The problem is that the output array (C=A*B) has as many rows as A and
      as many columns as B. I would think of initialising C with:
      >
      double C[A_rows][B_cols];
      >
      It looks like the compiler doesn't like this at all.
      >
      There is nothing obviously wrong with the above.  It would help to see
      the code or at least the error message.  In particular, the "best"
      solution will be different if the dimensions are fixed and know at
      compile time, are fixed but known only at run time, or if they are
      true arbitrary variables.  Also, are the dimensions small?
      >
      What is the best way to define C? could i use a structure data type
      for A and B, or do the dimensions of C need to be defined using
      pointers? Perhaps the malloc function comes in somewhere.
      >
      Maybe.  It is important to know if you can use C99.  C99 (the current
      standard) has some features that would make your task simpler.  Rather
      the talk about both, it would be better to know what version of C you
      are using/obliged to use.
      >
      I'm currently using the visual C++ 2008 compiler, but trying to keep
      the code as standard as possible so I can use it on embedded
      hardwarew, something like gumstix.
      Have you seen the comp.lang.c FAQ?  http://c-faq.com/
      >
      --
      Ben.
      Thanks for te fast reply. Here is my current code:

      #include <stdio.h>
      #include <stdlib.h>
      #include <math.h>


      int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;

      int A[3][3]={1,2,3,4,5,6,7 ,8,9};
      int B[3][3]={1,0,0,0,1,0,0 ,0,1};
      int C = malloc(Arows * Bcols * sizeof(int));


      main()
      {
      int row, col, i;

      if (Acols!=Brows){
      printf("Cannot compute; the number of columns of A
      equals the number of rows of B");
      for(;;);
      return 0;
      }


      // Calculate Product
      for(row=0; row<Arows; row++)
      {
      for(col=0; col<Bcols; col++)
      {
      C[row][col]=0;
      for(i=0; i<Acols; i++)
      {
      *C[row][col]=C[row][col] + ((A[row][i])*(B[i]
      [col])); }
      }
      }

      for(row=0; row<Arows; row++)
      {
      for(col=0; col<Bcols; col++)
      {
      // printf("%1d ", C[row][col]);
      }
      printf("\n");
      }
      for(;;);
      return 0;
      }

      I'm getting "error C2099: initializer is not a constant" from the line
      "int C = malloc(Arows * Bcols * sizeof(int));"

      As for the size of an array, I'd like to make my function capable of
      any size (but not huge enough to fill all the memory), this is
      requirement for my overall project. I know I haven't made the function
      take inputs properly yet, I'm just getting it to work first.

      Thanks
      Adam

      Comment

      • Ben Bacarisse

        #4
        Re: initialising array of unknown size (newbie)

        Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
        On Oct 9, 11:57 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
        >Adam Chapman <adam.chap...@s tudent.manchest er.ac.ukwrites:
        Im trying to migrate from programming in Matlab over to C. Im trying
        to make a simple function to multiply one matrix by the other. I've
        realised that C can't determine the size of a 2d array, so im
        inputting the dimensions of those myself.
        >>
        The problem is that the output array (C=A*B) has as many rows as A and
        as many columns as B. I would think of initialising C with:
        >>
        double C[A_rows][B_cols];
        >>
        It looks like the compiler doesn't like this at all.
        >>
        >There is nothing obviously wrong with the above.  It would help to see
        >the code or at least the error message.  In particular, the "best"
        >solution will be different if the dimensions are fixed and know at
        >compile time, are fixed but known only at run time, or if they are
        >true arbitrary variables.  Also, are the dimensions small?
        >>
        What is the best way to define C? could i use a structure data type
        for A and B, or do the dimensions of C need to be defined using
        pointers? Perhaps the malloc function comes in somewhere.
        >>
        >Maybe.  It is important to know if you can use C99.  C99 (the current
        >standard) has some features that would make your task simpler.  Rather
        >the talk about both, it would be better to know what version of C you
        >are using/obliged to use.
        >>
        I'm currently using the visual C++ 2008 compiler, but trying to keep
        the code as standard as possible so I can use it on embedded
        hardwarew, something like gumstix.
        OK, then I think C99 is out. The very best portability is to be had
        by aiming for the common intersection of C90 and C99. Essentially use
        "old C" but avoid anything that interferes with (or is wrong in) the
        new standard.
        >Have you seen the comp.lang.c FAQ?  http://c-faq.com/
        >>
        >--
        >Ben.
        best not to quote sig blocks. In fact, it is best to interleave your
        reply with the quoted test so you can comment on specific parts.
        Thanks for te fast reply. Here is my current code:
        >
        #include <stdio.h>
        #include <stdlib.h>
        #include <math.h>
        >
        >
        int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;
        It is not a good idea to duplicate information. It is better to
        define these in a manner that can be used to define the arrays.
        Maybe:

        #define AROWS 3
        #define ACOLS 3

        int A[AROWS][ACOLS] = {/*...*/};
        >
        int A[3][3]={1,2,3,4,5,6,7 ,8,9};
        int B[3][3]={1,0,0,0,1,0,0 ,0,1};
        int C = malloc(Arows * Bcols * sizeof(int));
        Well there is no need for malloc here. C can be defined thus:

        int C[3][3];

        but you knew that! I wonder why you thought malloc was needed (I'll
        explain the error later).
        main()
        This makes main and int rerturning function (correct) but in C99 this
        "implicit int" declaration is not permitted. It is much better just
        to write:

        int main(void)
        {
        int row, col, i;
        >
        if (Acols!=Brows){
        printf("Cannot compute; the number of columns of A
        equals the number of rows of B");
        for(;;);
        Eh? If you are having the "my message disappears unless this is
        there" then try to find the correct way to run your program so you can
        see its output (I can't help with that -- I simply don't know).
        return 0;
        }
        >
        >
        // Calculate Product
        for(row=0; row<Arows; row++)
        {
        for(col=0; col<Bcols; col++)
        {
        C[row][col]=0;
        for(i=0; i<Acols; i++)
        {
        *C[row][col]=C[row][col] + ((A[row][i])*(B[i]
        [col]));
        You just want to write C[row][col] = ... (i.e. no *). Also, C has a
        += operator that simplifies this sort of thing.
        }
        }
        }
        >
        for(row=0; row<Arows; row++)
        {
        for(col=0; col<Bcols; col++)
        {
        // printf("%1d ", C[row][col]);
        }
        printf("\n");
        }
        As a general point, I'd break this up into functions. At the very
        least, I'd have a print_matrix function, but I would also be tempted
        to put the A[X][i] * B[i][X] sum calculation into a function.
        for(;;);
        return 0;
        }
        >
        I'm getting "error C2099: initializer is not a constant" from the line
        "int C = malloc(Arows * Bcols * sizeof(int));"
        This is because, at file scope, an object can only be initialised with
        a compiler-time constant -- something that the compiler can work out.
        A call to malloc is not such a thing. In fact, for simplicity, C
        rules out all function calls in such positions, even those that could
        be worked out by the compiler.
        As for the size of an array, I'd like to make my function capable of
        any size (but not huge enough to fill all the memory), this is
        requirement for my overall project. I know I haven't made the function
        take inputs properly yet, I'm just getting it to work first.
        The "any size" is not really enough. The issue is whether the sizes
        can be know at compile time. It you need a set of very general array
        manipulation functions, be prepared for a lot of learning. Have you
        looked to see if there is some free code available to do what you
        need?

        If you want fully flexible array sizes and C90 code you may well be
        better off using arrays of pointers rather than 2D arrays. If there
        is any chance that you might have to change the representation of your
        arrays from one form to the other (maybe because of performance
        issues) it could well pay to start off to use an opaque type right
        from the start:

        struct matrix *matrix_create( size_t rows, size_t cols);
        element_t matrix_get(stru ct matrix *m, size_t row, size_t col);
        void matrix_set(stru ct matrix *m, size_t row, size_t col, element_t e);

        so you can change all the details at will later on.

        --
        Ben.

        Comment

        • Adam Chapman

          #5
          Re: initialising array of unknown size (newbie)

          On Oct 9, 1:49 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
          Adam Chapman <adam.chap...@s tudent.manchest er.ac.ukwrites:
          On Oct 9, 11:57 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
          Adam Chapman <adam.chap...@s tudent.manchest er.ac.ukwrites:
          Im trying to migrate from programming in Matlab over to C. Im trying
          to make a simple function to multiply one matrix by the other. I've
          realised that C can't determine the size of a 2d array, so im
          inputting the dimensions of those myself.
          >
          The problem is that the output array (C=A*B) has as many rows as Aand
          as many columns as B. I would think of initialising C with:
          >
          double C[A_rows][B_cols];
          >
          It looks like the compiler doesn't like this at all.
          >
          There is nothing obviously wrong with the above.  It would help to see
          the code or at least the error message.  In particular, the "best"
          solution will be different if the dimensions are fixed and know at
          compile time, are fixed but known only at run time, or if they are
          true arbitrary variables.  Also, are the dimensions small?
          >
          What is the best way to define C? could i use a structure data type
          for A and B, or do the dimensions of C need to be defined using
          pointers? Perhaps the malloc function comes in somewhere.
          >
          Maybe.  It is important to know if you can use C99.  C99 (the current
          standard) has some features that would make your task simpler.  Rather
          the talk about both, it would be better to know what version of C you
          are using/obliged to use.
          >
          I'm currently using the visual C++ 2008 compiler, but trying to keep
          the code as standard as possible so I can use it on embedded
          hardwarew, something like gumstix.
          >
          OK, then I think C99 is out.  The very best portability is to be had
          by aiming for the common intersection of C90 and C99.  Essentially use
          "old C" but avoid anything that interferes with (or is wrong in) the
          new standard.
          >
          Have you seen the comp.lang.c FAQ?  http://c-faq.com/
          >
          --
          Ben.
          >
          best not to quote sig blocks.  In fact, it is best to interleave your
          reply with the quoted test so you can comment on specific parts.
          >
          Thanks for te fast reply. Here is my current code:
          >
          #include <stdio.h>
          #include <stdlib.h>
          #include <math.h>
          >
          int Arows=3, Acols=3, Brows=3, Bcols=3, Crows, Ccols;
          >
          It is not a good idea to duplicate information.  It is better to
          define these in a manner that can be used to define the arrays.
          Maybe:
          >
          #define AROWS 3
          #define ACOLS 3
          >
          int A[AROWS][ACOLS] = {/*...*/};
          >
          >
          >
          int A[3][3]={1,2,3,4,5,6,7 ,8,9};
          int B[3][3]={1,0,0,0,1,0,0 ,0,1};
          int C = malloc(Arows  * Bcols * sizeof(int));
          >
          Well there is no need for malloc here.  C can be defined thus:
          >
            int C[3][3];
          >
          but you knew that!  I wonder why you thought malloc was needed (I'll
          explain the error later).
          >
          main()
          >
          This makes main and int rerturning function (correct) but in C99 this
          "implicit int" declaration is not permitted.  It is much better just
          to write:
          >
          int main(void)
          >
          {
             int row, col, i;
          >
             if (Acols!=Brows){
                        printf("Cannot compute; the number of columns of A
          equals the number of rows of B");
                     for(;;);
          >
          Eh?  If you are having the "my message disappears unless this is
          there" then try to find the correct way to run your program so you can
          see its output (I can't help with that -- I simply don't know).
          >
                     return 0;
             }
          >
              // Calculate Product
             for(row=0; row<Arows; row++)
             {
                     for(col=0; col<Bcols; col++)
                     {
                                     C[row][col]=0;
                             for(i=0; i<Acols; i++)
                             {
                               *C[row][col]=C[row][col] +((A[row][i])*(B[i]
          [col]));
          >
          You just want to write C[row][col] = ... (i.e. no *).  Also, C has a
          += operator that simplifies this sort of thing.
                                                    }
          >
                     }
             }
          >
             for(row=0; row<Arows; row++)
             {
                     for(col=0; col<Bcols; col++)
                     {
                     //      printf("%1d   ", C[row][col]);
                     }
                     printf("\n");
             }
          >
          As a general point, I'd break this up into functions.  At the very
          least, I'd have a print_matrix function, but I would also be tempted
          to put the A[X][i] * B[i][X] sum calculation into a function.
          >
             for(;;);
             return 0;
          }
          >
          I'm getting "error C2099: initializer is not a constant" from the line
          "int C = malloc(Arows  * Bcols * sizeof(int));"
          >
          This is because, at file scope, an object can only be initialised with
          a compiler-time constant -- something that the compiler can work out.
          A call to malloc is not such a thing.  In fact, for simplicity, C
          rules out all function calls in such positions, even those that could
          be worked out by the compiler.
          >
          As for the size of an array, I'd like to make my function capable of
          any size (but not huge enough to fill all the memory), this is
          requirement for my overall project. I know I haven't made the function
          take inputs properly yet, I'm just getting it to work first.
          >
          The "any size" is not really enough.  The issue is whether the sizes
          can be know at compile time.  It you need a set of very general array
          manipulation functions, be prepared for a lot of learning.  Have you
          looked to see if there is some free code available to do what you
          need?
          >
          If you want fully flexible array sizes and C90 code you may well be
          better off using arrays of pointers rather than 2D arrays.  If there
          is any chance that you might have to change the representation of your
          arrays from one form to the other (maybe because of performance
          issues) it could well pay to start off to use an opaque type right
          from the start:
          >
            struct matrix *matrix_create( size_t rows, size_t cols);
            element_t matrix_get(stru ct matrix *m, size_t row, size_t col);
            void matrix_set(stru ct matrix *m, size_t row, size_t col, element_t e);
          >
          so you can change all the details at will later on.
          >
          --
          Ben.- Hide quoted text -
          >
          - Show quoted text -
          Thanks. I want to eventually put the matrix multiplication function
          into a header so it can be called from future scripts. The malloc was
          for allocating memory for a matrix of size Arows*BCols, where Arows
          and Bcols could be any size and are inputs to the function. Very
          general I know, but still be useful when it finally works.
          Looking at http://cboard.cprogramming.com/archi...p/t-57095.html
          and http://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
          hard. I will need to read about pointers over again (and probably
          again and again!) but its all a good learnig experience I suppose.

          Thanks for your time,
          I appreciate it

          Adam

          Comment

          • Ben Bacarisse

            #6
            Re: initialising array of unknown size (newbie)

            Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
            On Oct 9, 1:49 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
            <snip>
            >best not to quote sig blocks.  In fact, it is best to interleave your
            >reply with the quoted test so you can comment on specific parts.
            If you intend to post to technical groups like this it will really
            help you if you copy the style of posting that is favoured here: snip
            lots (but keep enough context so your message makes sense) and
            interleave your reply with the quoted text you are replying to.

            <snip>
            >--
            >Ben.- Hide quoted text -
            >>
            It will also help if it looks like you are listening to the advice!
            Thanks. I want to eventually put the matrix multiplication function
            into a header so it can be called from future scripts.
            One usually puts function prototypes in header files. The code itself
            is usually elsewhere and is said to be "linked" with the code that
            calls it. For this sort of program it would be normal to write a
            library of matrix functions to link with future programs.
            The malloc was
            for allocating memory for a matrix of size Arows*BCols, where Arows
            and Bcols could be any size and are inputs to the function. Very
            general I know, but still be useful when it finally works.
            And it would have worked (nearly) if it had been in a function. In C
            it does not help to rough things out one way and then wrap it all up
            in a function because C has so many special rules. What can be done
            in one place is often not allowed elsewhere. It *really* helps to
            choose your functions first and sketch them out. If you don't, you
            will probably have to rewrite everything when you come to "wrap it up
            in a function" later.
            Yes it would. That is not good code. The variable names are hopeless
            and there are no re-usable functions even for the most obviously
            re-used code. The worst fault, though, is that that code does not
            check any of the allocations and if you plan to write code for an
            embedded device (I think you said this was your eventual target) then
            this simply can't ignored.

            Try reading:



            and look at Chapter 23. If you need some more basic stuff, try the
            introduction to C:


            I will need to read about pointers over again (and probably
            again and again!) but its all a good learnig experience I suppose.
            Note also that the code you cited does not really do 2D arrays. It
            does arrays of pointers to arrays. This is just one way to represent
            your data in "old C". The other is to pretend the array is flat (as
            you seemed to be doing with your malloc call) and using a
            multiplication to access the elements. Both have advantages and
            disadvantages. It is not clear which will be better for you.

            --
            Ben.

            Comment

            • Adam Chapman

              #7
              Re: initialising array of unknown size (newbie)

              On Oct 9, 3:32 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
              Adam Chapman <adam.chap...@s tudent.manchest er.ac.ukwrites:
              On Oct 9, 1:49 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
              <snip>
              best not to quote sig blocks.  In fact, it is best to interleave your
              reply with the quoted test so you can comment on specific parts.
              >
              If you intend to post to technical groups like this it will really
              help you if you copy the style of posting that is favoured here: snip
              lots (but keep enough context so your message makes sense) and
              interleave your reply with the quoted text you are replying to.
              >
              <snip>
              >
              --
              Ben.- Hide quoted text -
              >
              It will also help if it looks like you are listening to the advice!
              >
              Thanks. I want to eventually put the matrix multiplication function
              into a header so it can be called from future scripts.
              >
              One usually puts function prototypes in header files.  The code itself
              is usually elsewhere and is said to be "linked" with the code that
              calls it.  For this sort of program it would be normal to write a
              library of matrix functions to link with future programs.
              >
              The malloc was
              for allocating memory for a matrix of size Arows*BCols, where Arows
              and Bcols could be any size and are inputs to the function. Very
              general I know, but still be useful when it finally works.
              >
              And it would have worked (nearly) if it had been in a function.  In C
              it does not help to rough things out one way and then wrap it all up
              in a function because C has so many special rules.  What can be done
              in one place is often not allowed elsewhere.  It *really* helps to
              choose your functions first and sketch them out.  If you don't, you
              will probably have to rewrite everything when you come to "wrap it up
              in a function" later.
              >
              Looking athttp://cboard.cprogram ming.com/archive/index.php/t-57095.html
              andhttp://www.hermetic.ch/cfunlib/arrays/arrays.htm, it looks very
              hard.
              >
              Yes it would.  That is not good code.  The variable names are hopeless
              and there are no re-usable functions even for the most obviously
              re-used code.  The worst fault, though, is that that code does not
              check any of the allocations and if you plan to write code for an
              embedded device (I think you said this was your eventual target) then
              this simply can't ignored.
              >
              Try reading:
              >
               http://www.eskimo.com/~scs/cclass/int/top.html
              >
              and look at Chapter 23.  If you need some more basic stuff, try the
              introduction to C:
              >
               http://www.eskimo.com/~scs/cclass/notes/top.html
              >
              I will need to read about pointers over again (and probably
              again and again!) but its all a good learnig experience I suppose.
              >
              Note also that the code you cited does not really do 2D arrays.  It
              does arrays of pointers to arrays.  This is just one way to represent
              your data in "old C".  The other is to pretend the array is flat (as
              you seemed to be doing with your malloc call) and using a
              multiplication to access the elements.  Both have advantages and
              disadvantages.  It is not clear which will be better for you.
              >
              --
              Ben.
              Done it!
              For anyone looking this up, here is the code i ended up with:

              #include <stdio.h>
              #include <stdlib.h>
              #include <math.h>

              //double A[9], B[9];
              int Arows=3, Acols=3, Brows=3, Bcols=3;


              int A[3][3]={1,2,3,4,5,6,7 ,8,10};
              int B[3][3]={9,8,7,6,5,4,3 ,2,1};


              int **C;
              int i, j, k, row, col;
              main()
              {
              C=malloc(Arows * sizeof(int *));

              for(i=0; i<Arows; i++)
              {
              C[i]=malloc(Bcols * sizeof(int));
              for(j=0; j<Bcols; j++)
              {
              C[i][j]=0;

              for(k=0; k<Acols; k++)
              {
              C[i][j]+=A[i][k]*B[k][j];

              }
              printf("%0d ", C[i][j]);
              }
              printf("\n");
              }
              for(;;);
              return C;
              }


              Now I've got to set it up to take A and B as inputs and make the
              function return C. Will post when I've got it

              Adam

              Comment

              • Keith Thompson

                #8
                Re: initialising array of unknown size (newbie)

                Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
                [...]
                Done it!
                For anyone looking this up, here is the code i ended up with:
                >
                #include <stdio.h>
                #include <stdlib.h>
                #include <math.h>
                >
                //double A[9], B[9];
                int Arows=3, Acols=3, Brows=3, Bcols=3;
                >
                >
                int A[3][3]={1,2,3,4,5,6,7 ,8,10};
                int B[3][3]={9,8,7,6,5,4,3 ,2,1};
                You have 8 different occurences of the number 3 (not counting the two
                in the initializers), and the relationship among the various 3s is not
                sufficiently obvious. During maintenance, you could easily change one
                of them and forget to change another one.

                Also, Arows et al should really be constants. As written, you could
                legally change their values; to understand your code, a reader has to
                verify that you haven't done so.

                Here's how I'd write the above. (A side note: "const" doesn't mean
                "constant", it means read-only; "const int Arows = 3;" doesn't make
                Arows a constant.)

                #define AROWS 3
                #define ACOLS 3
                #define BROWS 3
                #define BCOLS 3

                int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
                int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };

                Note that the extra braces explicitly show the individual rows of the
                array.

                (Actually, I might replace the #define's with this:
                enum { AROWS=3, ACOLS=3, BROWS=3, BCOLS=3 };
                but some consider that an abuse of the enum feature.)
                >
                int **C;
                int i, j, k, row, col;
                Why are all these global? Why not declare them inside main?
                main()
                Better: int main(void)
                {
                C=malloc(Arows * sizeof(int *));
                malloc() can fail; it indicates this by returning a null pointer. You
                should always check for this. If nothing else, you can just abort the
                program.

                And here's a useful idiom:

                C = malloc(Arows * sizeof *C);

                Even if the type of C changes (say, if you want arrays of doubles
                rather than of ints), the call remains correct.
                for(i=0; i<Arows; i++)
                {
                C[i]=malloc(Bcols * sizeof(int));
                Again, you don't check whether the malloc call succeded.

                C[i] = malloc(Bcols * sizeof *C[i]);
                for(j=0; j<Bcols; j++)
                {
                C[i][j]=0;
                >
                for(k=0; k<Acols; k++)
                {
                C[i][j]+=A[i][k]*B[k][j];
                >
                }
                printf("%0d ", C[i][j]);
                }
                printf("\n");
                }
                for(;;);
                You know this is an infinite loop, right? Which means ...
                return C;
                .... that this return statement will never be executed.
                }
                >
                >
                Now I've got to set it up to take A and B as inputs and make the
                function return C. Will post when I've got it
                --
                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                Nokia
                "We must do something. This is something. Therefore, we must do this."
                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                Comment

                • Adam Chapman

                  #9
                  Re: initialising array of unknown size (newbie)

                  Thanks Keith, although your suggestions have brought up a lot of
                  errors.
                  Here is my current code:

                  #include <stdio.h>
                  #include <stdlib.h>
                  #include <math.h>


                  #define Arows 3;
                  #define Acols 3;
                  #define Brows 3;
                  #define Bcols 3;


                  float A[Arows][Acols]={{1,2,3},{4,5, 6},{7,8,9}};
                  float B[Brows][Bcols]={{9,8,7},{6,5, 4},{3,2,1}};
                  float C;


                  main(){
                  C=mat_mult();
                  for(;;); // to stop display closing down (needs proper fix)

                  }


                  mat_mult()
                  {
                  float **C;
                  int i, j, k;
                  C = malloc(Arows * sizeof *C);

                  for(i=0; i<Arows; i++)
                  {
                  C[i] = malloc(Bcols * sizeof *C[i]);
                  for(j=0; j<Bcols; j++)
                  {
                  C[i][j]=0;

                  for(k=0; k<Acols; k++)
                  {
                  C[i][j]+=A[i][k]*B[k][j];

                  }
                  printf("%0f ", C[i][j]);
                  }
                  printf("\n");
                  }

                  return C;
                  }

                  #define AROWS 3
                  #define ACOLS 3
                  #define BROWS 3
                  #define BCOLS 3
                  >
                  int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
                  int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };
                  gives "error C2143: syntax error : missing ']' before ';' "

                  Also, I keep getting this warning: "warning C4013: 'mat_mult'
                  undefined; assuming extern returning int" from the line
                  C=mat_mult();
                  Sorry if I sound stupid. This is quite difficult for me to get my head
                  around

                  Adam

                  Comment

                  • Lew Pitcher

                    #10
                    Re: initialising array of unknown size (newbie)

                    On October 9, 2008 15:11, in comp.lang.c, Adam Chapman
                    (adam.chapman@s tudent.manchest er.ac.uk) wrote:
                    Thanks Keith, although your suggestions have brought up a lot of
                    errors.
                    Here is my current code:
                    >
                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <math.h>
                    >
                    >
                    #define Arows 3;
                    Note what the macro Arows expands to
                    #define Acols 3;
                    Note what the macro Acols expands to
                    #define Brows 3;
                    Note what the macro Brows expands to
                    #define Bcols 3;
                    Note what the macro Bcols expands to
                    >
                    >
                    float A[Arows][Acols]={{1,2,3},{4,5, 6},{7,8,9}};
                    Hand expanding the macros, this line reads
                    float A[3;][3;]={{1,2,3},{4,5, 6},{7,8,9}};
                    Are you sure that you want this?
                    float B[Brows][Bcols]={{9,8,7},{6,5, 4},{3,2,1}};
                    Hand expanding the macros, this line reads
                    float B[3;][3;]={{9,8,7},{6,5, 4},{3,2,1}};
                    Again, are you certain that this is what you want?
                    float C;
                    >
                    >
                    main(){
                    At this point, the function mat_mult() has not been declared or defined. The
                    compiler will /assume/ that mat_mult() takes an unknown set of arguments,
                    and returns an integer. Is this what you want?
                    C=mat_mult();
                    OK, the integer returned by mat_mult() is now converted to a float.
                    for(;;); // to stop display closing down (needs proper fix)
                    >
                    }
                    >
                    >
                    mat_mult()
                    This is an error in C99 - you need to tell the compiler what the type is of
                    the return value. In previous levels of C, the default is an integer. So,
                    either you have a syntax error (in C99) or you are returning an integer (in
                    prior levels of C).
                    {
                    float **C;
                    Here, you define an automatic variable with the same name as a file-duration
                    static variable. /This/ local variable is the one that the function will
                    use.
                    int i, j, k;
                    C = malloc(Arows * sizeof *C);
                    Hmmmmm.....

                    I'll leave it to others to comment on the rest of /this code. There's
                    something very suspicious here, but I don't feel qualified enough to give
                    it the proper analysis.
                    >
                    for(i=0; i<Arows; i++)
                    {
                    C[i] = malloc(Bcols * sizeof *C[i]);
                    for(j=0; j<Bcols; j++)
                    {
                    C[i][j]=0;
                    >
                    for(k=0; k<Acols; k++)
                    {
                    C[i][j]+=A[i][k]*B[k][j];
                    >
                    }
                    printf("%0f ", C[i][j]);
                    }
                    printf("\n");
                    }
                    >
                    return C;
                    You defined C as a pointer to a pointer to a float.
                    However,
                    a) you defined the function as returning an integer (assuming < C99)
                    b) you convert the integer to a float in your main() function
                    Oops. A pointer is neither an integer, nor a float.


                    }
                    >
                    >
                    > #define AROWS 3
                    > #define ACOLS 3
                    > #define BROWS 3
                    > #define BCOLS 3
                    >>
                    > int A[AROWS][ACOLS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
                    > int B[BROWS][BCOLS] = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} };
                    >
                    gives "error C2143: syntax error : missing ']' before ';' "
                    >
                    Also, I keep getting this warning: "warning C4013: 'mat_mult'
                    undefined; assuming extern returning int" from the line
                    >C=mat_mult() ;
                    >
                    Sorry if I sound stupid. This is quite difficult for me to get my head
                    around
                    >
                    Adam
                    --
                    Lew Pitcher

                    Master Codewright & JOAT-in-training | Registered Linux User #112576
                    http://pitcher.digitalfreehold.ca/ | GPG public key available by request
                    ---------- Slackware - Because I know what I'm doing. ------


                    Comment

                    • Adam Chapman

                      #11
                      Re: initialising array of unknown size (newbie)

                      >the function mat_mult() has not been declared or defined. The
                      compiler will /assume/ that mat_mult() takes an unknown set of arguments,
                      and returns an integer. Is this what you want?
                      >
                      Ah I see, i need

                      float mat_mult();

                      declared. This will make the output of mat_mult a float.
                      {
                      float **C;
                      >
                      Here, you define an automatic variable with the same name as a file-duration
                      static variable. /This/ local variable is the one that the function will
                      use.
                      Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
                      within the mat_mult function with "float **d".

                      So now I have

                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <math.h>


                      #define Arows 3
                      #define Acols 3
                      #define Brows 3
                      #define Bcols 3


                      float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
                      float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

                      float mat_mult();

                      main(){
                      float C;
                      C=mat_mult();
                      printf("%f",C[0][0]);
                      for(;;);
                      }


                      mat_mult()
                      {
                      float **d;
                      int i, j, k;
                      d = malloc(Arows * sizeof *d);

                      for(i=0; i<Arows; i++)
                      {
                      d[i] = malloc(Bcols * sizeof *d[i] );
                      for(j=0; j<Bcols; j++)
                      {
                      d[i][j]=0;

                      for(k=0; k<Acols; k++)
                      {
                      d[i][j]+=A[i][k]*B[k][j];

                      }
                      printf("%0f ", d[i][j]);
                      }
                      printf("\n");
                      }
                      return d;
                      }

                      Still need to define the input type for mat_mult, but my main concern
                      is that I get errors with the printf in main(). It says " error C2109:
                      subscript requires array or pointer type". Im not sure if main has
                      seen the output as a 2d array.

                      Comment

                      • Keith Thompson

                        #12
                        Re: initialising array of unknown size (newbie)

                        Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
                        [...]
                        So now I have
                        >
                        #include <stdio.h>
                        #include <stdlib.h>
                        #include <math.h>
                        >
                        >
                        #define Arows 3
                        #define Acols 3
                        #define Brows 3
                        #define Bcols 3
                        >
                        >
                        float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
                        float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
                        >
                        float mat_mult();
                        This declares that mat_mult takes an unspecified but fixed
                        number of arguments. If it takes no arguments, say so:

                        float mat_mult(void);

                        main(){
                        Make this:

                        int main(void) {

                        float C;
                        C=mat_mult();
                        Ok.
                        printf("%f",C[0][0]);
                        You just declared C as a float. Why are you trying to indix it as if
                        it were a two-dimensional array?
                        for(;;);
                        Why the infinite loop?
                        }
                        >
                        >
                        mat_mult()
                        Again, make this:

                        float mat_mult(void)

                        Incidentally, it usually makes more sense to use double rather than
                        float.

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                        Nokia
                        "We must do something. This is something. Therefore, we must do this."
                        -- Antony Jay and Jonathan Lynn, "Yes Minister"

                        Comment

                        • Lew Pitcher

                          #13
                          Re: initialising array of unknown size (newbie)

                          (Oops - I mailed instead of posting - Apologies to adam and the rest of
                          c.l.c)

                          Posted as per personal dictum ("you post here, you read here")

                          On October 9, 2008 16:36, in comp.lang.c, Adam Chapman
                          (adam.chapman@s tudent.manchest er.ac.uk) wrote:
                          >>the function mat_mult() has not been declared or defined. The
                          >compiler will /assume/ that mat_mult() takes an unknown set of arguments,
                          >and returns an integer. Is this what you want?
                          >>
                          Ah I see, i need

                          float mat_mult();

                          declared. This will make the output of mat_mult a float.
                          {
                          float **C;
                          >>
                          >Here, you define an automatic variable with the same name as a
                          >file-duration static variable. /This/ local variable is the one thatthe
                          >function will use.
                          Ok, so I changed all the "C's" in mat_mult to "d's", and deffined d
                          within the mat_mult function with "float **d".

                          So now I have

                          #include <stdio.h>
                          #include <stdlib.h>
                          #include <math.h>


                          #define Arows 3
                          #define Acols 3
                          #define Brows 3
                          #define Bcols 3


                          float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
                          float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };

                          float mat_mult();

                          main(){
                              float C;
                          Here, C is declared and defined as a float

                          C=mat_mult();
                          printf("%f",C[0][0]);
                          Here, you code as if C were a two-dimensional array (with unknown
                          dimensions)

                          No.

                          Try
                            printf("%f\n",C );

                              for(;;);
                          }
                          Prior to your main() function, you declared mat_mult() as returning a float.
                          Below, you define mat_mult() as returning an int.
                          mat_mult()
                          This should be...
                            float mat_mult()
                          {

                          OK, I just don't have the words to explain how wrong this function is.

                          From your original main(), I presumed that you wanted the function to return
                          a single floatingpoint value, but on second-read, I see that you really
                          intend for the function to return an array of floatingpoint values.
                          However, you /really/ haven't coded that.

                          First off, in C, you cannot return an array. You can either return a struct
                          (or union) that /contains/ an array, or you can return a pointer to the
                          first element of an array. That's it.

                          Secondly, arrays are contigiously allocated space. Elements of an arrayof
                            type name[size];
                          can either be referenced by
                            name[index]
                          or
                            *(name+index)

                          A two-dimensional array can be thought of as a one-dimensional array, each
                          element of which is a one-dimensional array.

                          So, elements of an array of
                            type name[n_rows][n_cols];
                          can either be referenced as
                            name[row][col]
                          or as
                            *(name + (row * n_cols) + col)

                          See how, as a pointer expression, the compiler /needs/ to know the sizeof
                          the inner one-dimensional array?

                          Similarly, elements of an array of
                            type name[n_pages][n_rows][n_cols];
                          can either be referenced as
                            name[page][row][col]
                          or as
                            *(name + (page * n_rows * n_cols) + (row * n_cols) + col)


                          OK, now in /your/ code below, you don't build a multi-dimensional array..
                          Instead, you build a *tree* of pointers. Since the dimensions are unknown
                          at compile time, compile-time shortcuts (like array subscripting) aren't
                          going to work. You have to dereference each pointer and pointer-to-pointer
                          to get to the data underneath.

                          I'm going to ignore a lot of things below (like testing malloc() for
                          success, and size mismatches, and the like) and try to cut to the heartof
                          the matter
                          float **d;
                          d is an unitialized pointer to a pointer to a float.
                              int i, j, k;
                          d = malloc(Arows * sizeof *d);
                          d now points to space for three pointers.
                          *d is permitted to be a pointer to a float
                           
                          for(i=0; i<Arows; i++)
                          {
                          d[i] = malloc(Bcols * sizeof *d[i] );
                          Since you don't have multiple dimensions to contend with, you can get away
                          with
                            d[i]
                          being equivalent to
                            *(d+i)
                          This works for this code, here, but /will not/ work for your later use as
                          access to a multi-dimensional array

                          each of the three spaces that d can access now points to some space. The
                          size of the space allocated for each of those elements is three times the
                          size of a pointer-to-float (d is a pointer-to a pointer-to a float, so *d
                          resolves to be a pointer-to a float. Since *d is the same as *(d+0), and
                          *(d+0) is the same as d[0], then d[0] resolves to a pointer-to a float,and
                          consequently so does d[i].) This is important, because you asked malloc()
                          to allocate some space for you based on /this size/. You didn't get the
                          space for three floatingpoint numbers; you got what you asked for - the
                          space for three pointers.

                          for(j=0; j<Bcols; j++)
                          {
                          d[i][j]=0;
                          First off, you can't access your pointer-tree in this manner. It is nota
                          multi-dimensional array, but is a tree of pointers and
                          pointers-to-pointers.

                          Secondly, you haven't allocated space for the floatingpoint values yet,so
                          trying to assign anything other than a pointer value is futile and an
                          error.

                          Thirdly (and not too consequentially ), 0 is not a floatingpoint value.
                          However 0.0 is. The good news is that, had the  left-hand-side of the
                          statement correctly resolved to a floatingpoint data type, C would have
                          converted your integer 0 to floatingpoint 0.0 for you.

                          for(k=0; k<Acols; k++)
                          {
                          d[i][j]+=A[i][k]*B[k][j];

                          }
                          printf("%0f   ", d[i][j]);
                          }
                          printf("\n");
                          }
                          return d;
                          No. You are returning a pointer. A pointer to an automatic variable that
                          disappears /with/ the return. You don't want to do this.
                          }

                          Still need to define the input type for mat_mult, but my main concern
                          is that I get errors with the printf in main(). It says " error C2109:
                          subscript requires array or pointer type". Im not sure if main has
                          seen the output as a 2d array.
                          See above
                          --
                          Lew Pitcher

                          Master Codewright & JOAT-in-training | Registered Linux User #112576
                          http://pitcher.digitalfreehold.ca/ | GPG public key available by request
                          ---------- Slackware - Because I know what I'm doing. ------


                          Comment

                          • Lew Pitcher

                            #14
                            Re: initialising array of unknown size (newbie)

                            On October 9, 2008 17:24, in comp.lang.c, Lew Pitcher
                            (lpitcher@teksa vvy.com) wrote:
                            [snip]
                            Prior to your main() function, you declared mat_mult() as returning a
                            float. Below, you define mat_mult() as returning an int.
                            >
                            >mat_mult()
                            >
                            This should be...
                            float mat_mult()
                            >{
                            [snip]
                            >float **d;
                            [snip]
                            >return d;
                            >
                            No. You are returning a pointer.
                            Oops... The following is incorrect...
                            A pointer to an automatic variable that
                            disappears /with/ the return.
                            The pointer is pointing to valid malloc()ed memory. It won't disappear when
                            the function returns.
                            You don't want to do this.
                            >
                            >}

                            --
                            Lew Pitcher

                            Master Codewright & JOAT-in-training | Registered Linux User #112576
                            http://pitcher.digitalfreehold.ca/ | GPG public key available by request
                            ---------- Slackware - Because I know what I'm doing. ------


                            Comment

                            • Ben Bacarisse

                              #15
                              Re: initialising array of unknown size (newbie)

                              Adam Chapman <adam.chapman@s tudent.manchest er.ac.ukwrites:
                              <snip>
                              So now I have
                              >
                              #include <stdio.h>
                              #include <stdlib.h>
                              #include <math.h>
                              >
                              >
                              #define Arows 3
                              #define Acols 3
                              #define Brows 3
                              #define Bcols 3
                              >
                              >
                              float A[Arows][Acols]={ {1,2,3}, {4,5,6}, {7,8,9} };
                              float B[Brows][Bcols]={ {9,8,7}, {6,5,4}, {3,2,1} };
                              Just so I can improve my style, what was it about Keith Thompson
                              suggesting this that made you take note when you seemed ignore the
                              same suggestion from me several messages ago? :-)

                              <snip>
                              float **d;
                              int i, j, k;
                              d = malloc(Arows * sizeof *d);
                              You are heading into trouble here. It is very unwise to use both a 2D
                              array like A and B and an array of pointers like d. You will end up
                              with code that can't be combined in useful ways. The result of the
                              matrix multiply is in a different format (in C terms a different type)
                              to the data that is operates on. You would not, for example, be able
                              to multiply the result of a multiplication.

                              You should pick either the contiguous representation used for A and B
                              or the array of pointers representation used for d and not mix them.

                              --
                              Ben.

                              Comment

                              Working...