Thread: passing an array created with malloc as a param

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    48

    passing an array created with malloc as a param

    Hi folks, i want to know how can i pass an array wich has been created with malloc() as a param. I have tried out this:

    First try:
    Code:
    //array declaration
    
    int (*myimage)[6];
    
    myimage = (int (*)[6]) malloc ( sizeof (int) * 10 * 6 );
      
    myimage[0][3] = 5;
    
    
    //function call
    
    readTIFFImageArray ( "" , 90 , 100 , myimage ); 
    
    
    //test function declaration
    
    void readTIFFImageArray ( char *filename , unsigned long imageWidth ,
                              unsigned long imageHeight , int array[0][0] )
    {
        printf ( "%i\n" , array[0][3] );          
    }
    With this way, it works fine. But i have a serious doubt. When i create my array, i'm determining that it will be a 10x6 matrix. But when i set as a param i'm determining that it will have 1x1 elements. So, what are the secondary effects that might appear with this code?


    Second way:

    Code:
    //array declaration
    
    // ... same as first try
    
    
    //function call
    
    // ... same as first try
    
    
    //test function declaration and implementation
    
    void readTIFFImageArray ( char *filename , unsigned long imageWidth ,
                              unsigned long imageHeight , int array[][] )
    {
        printf ( "%i\n" , array[0][3] );          
    }
    If i write code like it's shown above, it throws the following error:

    invalid use of array with unspecified bounds.


    So wich is the correct way of doing it?
    Thanks in advance.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You always have to pass the (correct!) second (and later) sizes of an array when you pass an array as a parameter. You should get errors, or at least warnings, about the first too -- you're not actually passing a 0-size array, and I don't even think that means anything.

  3. #3
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    Here's how i did it:

    Code:
    void readTIFFRGBImageArray ( const char *filename , tiff_header hdr , rgb_pixel array[hdr.imageWidth.singleValue][hdr.imageHeight.singleValue] );
    Thanks.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The easiest way would simply be to make the type of the arguments match.
    Since your variable is of type int (*myimage)[6], the function should look like:
    Code:
    void readTIFFImageArray ( char *filename , unsigned long imageWidth ,
                              unsigned long imageHeight , int (*array)[6] )
    But if you insist on passing it as an array, then you need to specify the correct column dimension:
    Code:
    void readTIFFImageArray ( char *filename , unsigned long imageWidth ,
                              unsigned long imageHeight , int array[][6] )
    Passing a 0-dimension array will cause errors in your code since the compiler will use the known column dimension to calculate the correct offset when storing and retrieving data.
    If an array is 5x5, and you access [3][4], the actual offset is 3 x 5 + (4 + 1), so 3 x 5 + 5 = 20.
    But if you pass that as an array with a lesser column dimension, such as [][0], you would get this when accessing [3][4]:
    3 x 1 + (4 + 1) = 3 x 1 + 5 = 8!
    So it writes (or reads) to/from the incorrect memory location. That's why you need to pass correct size.

    Disclaimer: The post may be subject to some small errors, but the general idea is correct. I reserve the right to be corrected.
    Last edited by Elysia; 02-19-2008 at 04:50 AM.
    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.

  5. #5
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    That was quite an explanation, thanks for taking your time to explain it to me. I'm gonna do it making the type of the arguments match. It's simply and more legible.

  6. #6
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    I have a new problem about it. I declare a var of type rgb_pixel (*) [size]. I have a structure named bmp_image wich one of its member needs to be a var of the type above declared. But size , is not an arbitrary number, it depends on bitmap image height. So, i try to do the same as i did with functions, this is to use a param of the same function to retrieves the image height, just like this:

    Code:
    void readBmpSingleSampleImageArray ( const char *filename , bmp_headers hdrs , 
    singleSample_pixel (*array)[hdrs.header.imageHeight] );
    The structure is declared like this:

    Code:
    typedef struct s_bmp_image
    {
        bmp_headers headers;
        rgb_pixel (*RGBPixels)[headers.header.imageHeight];
    }bmp_image;
    But it throws the following error:

    'headers' undeclared here (not in a function)

    Wich is the way of get this done? is there a way? or i just need to structure my code on a different way?
    Last edited by mariano_donati; 02-19-2008 at 08:13 PM.

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    I have thought about a solution, wich i'm implementing by now, but i have a doubt.
    I define a const named MAXIMAGEHEIGHT, so in my structure i declare the array with this arbitrary number (set to 2048). When i allocate memory for my array i do the following:

    Code:
    // declare var
    bmp_image img;
    rgb_pixel (*pixels)[hdrs.header.imageHeight];
    
    // allocate memory
    pixels = ( rgb_pixel (*)[hdrs.header.imageHeight] ) malloc ( sizeof ( rgb_pixel ) * hdrs.header.imageWidth * hdrs.header.imageHeight );
    
    // we get pixels from bitmap and put them into pixels array
    readBmpRGBImageArray ( filename , hdrs , pixels );
    
    // set img.RGBPixels to pixels array
    img.RGBPixels = pixels;
    Here, hdrs.header.imageHeight will always be minor or equal to MAXIMAGEHEIGHT. I have a doubt about what does happen in last line if it's minor than const. Will img.RGBPixels be automatically reallocated, changing its size to necessary number of bytes?. Do i have to reallocate it myself to assure me that my array only occupies memory to storage hdrs.header.imageHeight elements and not MAXIMAGEHEIGHT?. I hope you can save my doubt.

  8. #8
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    Can you kindly post the names of the header files you are including?
    The declaration of the struct, is wrong, wrong, wrong.
    You are assuming that there is an object, named 'headers' with initialized at compile time values, which even if there was one you probably need different imageHeight values for every bmp_image you declare. Also the call to readBmpSingleSampleImageArray is definately wrong. The third argument cannot have (1) two identifier components, (2) if it is an array of constant length, it should be declared in the header file of the function, and not acquired through run-time data, or else it is a pointer.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    Thanks for replying.
    About the call of readBmpSingleSampleImageArray call, the third argument is this:

    singleSample_pixel (*array)[hdrs.header.imageHeight]

    In green i declare param's type. It's singleSample_pixel. In blue, i'm declaring an identifier <array>, wich is a pointer to singleSample_pixel. In red, i'm determining 2nd dimention's array's size. This type is the exact type i use to allocate memory for the array. My application works fine with it, and doesn't throw any warning or error about it. Is it wrong to do it like this? even C compiler accepts it, is there a chance that in some cases my application don't work?.
    About second thing you remark, just like you said, it's a number wich its value depends on the bitmap image, and i cannot declare an array of constant length.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You simply can't define an array on the stack (or arguments) with a runtime filled variable. There is an exception in C99, but for local variables. For dynamic size, you need a pointer or if you need a 2D-array, you need a pointer-to-pointer, **.
    Last edited by Elysia; 02-20-2008 at 12:25 PM.
    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.

  11. #11
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    How i would do that?, i can't get the idea of it. If a need a pointer-to-pointer param, does it mean that i have to change all var's type as the one i said above? (rgb_pixel (*)[size]). Because i just tried to do it, changing only param's type to pointer-to-pointer, but it says that i'm passing an arg from incompatible pointer type. So how do i do what you said elysia?. Apologizes my ignorance, i never used pointers-to-pointers vars.

  12. #12
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    I was looking for it around the net, and i should change the way i'm declaring vars. The only way i knew how declaring a 2D array type was array_type (*array)[size]. But in C a 2D array is an array of arrays, so it's a pointer of pointers, and that's (i think) a better way of seeing it.
    Thanks.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, a pointer to a pointer is basically a pointer to an array of pointers to allocated memory.
    So you need to use that if you need dynamic arrays.
    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. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  2. Type and nontype parameters w/overloading
    By Mr_LJ in forum C++ Programming
    Replies: 3
    Last Post: 01-02-2004, 01:01 AM
  3. multidimensional array and malloc
    By Kinasz in forum C Programming
    Replies: 4
    Last Post: 12-20-2003, 02:15 PM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM