Thread: Casting 2D arrays

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

    Casting 2D arrays

    I'm trying to cast a 2D array of unsigned shorts to a 2D array of unsigned chars. I've done this with 1D arrays, but I can't seem to get this to work. What I have kind of works in that a few values print out correctly, but most are wrong.

    Code:
    	int i,j, count;
    
    	USHORT **test;
    
    	test = (USHORT **)malloc(sizeof(USHORT)*4);
    
    	count=0;
    	for(i=0;i<4;i++)
    	{
    		for(j=0;j<4;j++)
    		{
    			test[i] = (USHORT *)malloc(sizeof(USHORT)*4);
    			count++;
    			test[i][j] = count;
    			count++;
    			test[i][j] = test[i][j] | count<<8;
    		}
    	}
    
    	for(i=0;i<4;i++)
    	{
    		for(j=0;j<8;j++)
    		{
    			printf("%d\n", ((UCHAR **)test)[i][j]);
    		}
    	}
    Basically, I'm trying to avoid doing the right shift in the print out. Does anyone see what this issue is?

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    First malloc allocates pointers, so it should be
    Code:
    test = (USHORT **)malloc(sizeof(USHORT *)*4);
    Also, you should not be malloc()'ing rows inside the inner loop. That should go between the for i and the for j.
    Last edited by nonoob; 04-06-2011 at 09:25 AM.

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Ha! Oh man, silly error. I should have seen that. Thanks.

    Is there anyway to do this with test being declared as test[X]N]?

  4. #4
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Recommended idiom is:

    Code:
    p = malloc( sizeof(*p) );

  5. #5
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Quote Originally Posted by Bayint Naung View Post
    Recommended idiom is:

    Code:
    p = malloc( sizeof(*p) );
    I see this said on this forum a lot. I've never had it compile. My compiler always says, "cannot convert from void * to <insert type here>".

  6. #6
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Quote Originally Posted by homer_3 View Post
    Ha! Oh man, silly error. I should have seen that. Thanks.

    Is there anyway to do this with test being declared as test[X]N]?
    Yes you can get rid of all the malloc and just define

    USHORT test[4][4];

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by homer_3 View Post
    I see this said on this forum a lot. I've never had it compile. My compiler always says, "cannot convert from void * to <insert type here>".
    Because you aren't actually using a C compiler...
    That's a C++ requirement.

    What are you using?

    Check your IDE and compiler settings... if it cannot be set for C compliance (C-99 in particular) you need to dump the braindead thing and find a proper C compiler.

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Quote Originally Posted by CommonTater View Post
    Because you aren't actually using a C compiler...
    That's a C++ requirement.
    Interesting, didn't know that. I'm using MSVSC++, changed the compiler to C and it didn't complain.

    USHORT test[4][4];
    No, I tried that. I get bad memory access using both the C and C++ compiler.

  9. #9
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    The printout part has to change:
    Code:
    for(i=0;i<32;i++)
        {
            printf("%d\n", ((UCHAR *)&test)[i]);
        }

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > No, I tried that. I get bad memory access using both the C and C++ compiler.
    Probably because the 2nd pair of loops run off into the weeds.

    > for(i=0;i<4;i++)
    > for(j=0;j<8;j++)

    If the arrays didn't work, then trying to use malloc to achieve the same thing wouldn't change that. Sure, it might stop crashing (immediately), but the underlying problem would still be there to bite you in the ass as some point later on. Only then, it would be a much more obscure problem for you to try and diagnose.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Quote Originally Posted by Salem View Post
    > No, I tried that. I get bad memory access using both the C and C++ compiler.
    Probably because the 2nd pair of loops run off into the weeds.

    > for(i=0;i<4;i++)
    > for(j=0;j<8;j++)
    No it doesn't. In the second set of loops I'm looping 1 byte at a time because I casted to a char. The 1st set of loops goes at 2 bytes at a time because it's working on shorts.

    Using malloc works because the "elements" in the 2nd dimension of the array are pointers. So I can offset to the 1st dimension pointer and then offset again off that pointer.

    [][] doesn't work because a continuous block of memory is allocated for the 2d array and element [i][j] is really i*Length+j. I was hoping someone knew of any tricks to get this to work how I have above.

    But I don't get why I get a bad memory access error when i=0 and j=0. That should still be valid because it's the 1st element.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Oh, I see now.

    Well it would work, if you got the type of your pointers correct. A 2D array is NOT a ** pointer.

    Try this
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
      unsigned short a[4][4];
      unsigned char (*arr)[8] = (unsigned char (*)[8])a;
      int i,j;
      for ( i = 0 ; i < 4 ; i++ ) {
        for ( j = 0 ; j < 4 ; j++ ) {
          a[i][j] = (i << 8) + j;
        }
      }
      for ( i = 0 ; i < 4 ; i++ ) {
        for ( j = 0 ; j < 8 ; j++ ) {
          printf("%d ", arr[i][j] );
        }
        printf("\n");
      }
      return 0;
    }
    
    $ gcc bar.c
    $ ./a.out 
    0 0 1 0 2 0 3 0 
    0 1 1 1 2 1 3 1 
    0 2 1 2 2 2 3 2 
    0 3 1 3 2 3 3 3
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Cool, that works nicely.

  14. #14
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Congtrats on the use of
    unsigned char (*arr)[8] = (unsigned char (*)[8])a;

    I'll have to bend my head around that. I don't see why you need a '*'. There are no array of pointer. I would have tried char [][8]. Plus, it should be illegal to define a variable whose first use is inside parenthesis (except function pointers - and those are a headache too)

    I think you are taking advantage of undocumented compiler oversights.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    There's nothing magic about it at all.

    char *arr[8] is an array of 8 pointers to characters.
    char (*arr)[8] is a pointer to an array of 8 characters.

    If you were wanting to pass a 2D array to a function, you would have the same thing.

    Namely
    char arr[4][4];

    and
    void func( char arr[4][4] );

    But this would work just as well
    void func( char (*arr)[4] );

    Once you understand that you can point to the whole array, and not just the first element of the array, then it all follows quite naturally.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. passing dynamicaly allocated 2d arrays
    By s_siouris in forum C Programming
    Replies: 6
    Last Post: 05-25-2008, 04:19 PM
  2. Help with 2d arrays
    By thamiz in forum C Programming
    Replies: 25
    Last Post: 05-25-2008, 05:06 AM
  3. 2D Array's, assigning chars.
    By gman89 in forum C Programming
    Replies: 9
    Last Post: 04-26-2008, 11:03 PM
  4. returning 2D arrays
    By ... in forum C++ Programming
    Replies: 2
    Last Post: 09-02-2003, 12:28 PM
  5. 2d arrays: H e l p!
    By scuba22 in forum C++ Programming
    Replies: 4
    Last Post: 11-04-2002, 05:54 PM