Thread: casting to pointer of an array

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    52

    casting to pointer of an array

    How do you cast to a pointer of an array?

    for example I would like to do the following:

    Code:
    int *data[2];
    data = (int *[2]) malloc(sizeof(int[2])*SIZE);
    I get an error for the cast "(int *[2])". And I also tried "(int[2]*)" and "(int**)"

    I know I could just create a an array of ints and make it twice the size but it makes more visual sense to pair values like this.

    I also require the cast because the gcc compiler throws an error otherwise.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    It's a precedence issue with your definition of data. The brackets have a higher precedence than the asterisk so you're defining an array of 2 int pointers. To define a pointer to int[2] arrays you need parentheses like this:
    Code:
        int (*data)[2];
    And you of course don't need the cast on malloc.

  3. #3
    Registered User
    Join Date
    Jan 2016
    Posts
    52
    Quote Originally Posted by algorism View Post
    Code:
        int (*data)[2];
    And you of course don't need the cast on malloc.
    Firstly, wouldn't this give me an array of 2 int pointers? I want a pointer to int arrays of size 2
    Second my gcc compiler throws an error without the cast. NOT a warning; "error: incompatible types when assigning to type ‘int *[2]’ from type ‘void *’"

    EDIT:

    to be clear, the error for my cast is not about it being a wrong cast, the syntax itself is wrong. The code I posted may be a little misleading with the cast I used so let me post that again with a more telling cast:
    Code:
    int *data[2];
    data = (int[2]*) malloc(sizeof(int[2])*SIZE);
    and the error for the second line is: "error: expected ‘)’ before ‘*’ token"
    Last edited by jdodle; 05-31-2016 at 03:44 PM.

  4. #4
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by jdodle View Post
    Firstly, wouldn't this give me an array of 2 int pointers? I want a pointer to int arrays of size 2
    Second my gcc compiler throws an error without the cast. NOT a warning; "error: incompatible types when assigning to type ‘int *[2]’ from type ‘void *’"
    Firstly, you're an idiot.
    Secondly, screw you.

  5. #5
    Registered User
    Join Date
    Jan 2016
    Posts
    52
    Quote Originally Posted by algorism View Post
    Firstly, you're an idiot.
    Secondly, screw you.
    whoa... whats the hostility for? I was just trying to clarify what the problem is... I'm sorry if it came off as arrogant or something.

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Second my gcc compiler throws an error without the cast. NOT a warning; "error: incompatible types when assigning to type ‘int *[2]’ from type ‘void *’"
    How are you compiling this program? Are you by chance using a C++ compiler instead of a C compiler? If you're using malloc() correctly with a C compiler you shouldn't need the cast.

    I'm sorry if it came off as arrogant or something.
    It did.

    Jim

  7. #7
    Registered User
    Join Date
    Jan 2016
    Posts
    52
    Quote Originally Posted by jimblumberg View Post
    How are you compiling this program? Are you by chance using a C++ compiler instead of a C compiler?
    I am using gcc with flags "-std=c99 -g -O3". However it could have been adjusted, are there ways to change how the compiler recognizes errors and warnings when installing gcc?

    In any case, the question is not really about how to fix the error or get around the error (I know how I can avoid it), it is about how to cast to a pointer for array's of size N. fixing the error is more of a side effect.
    Last edited by jdodle; 05-31-2016 at 04:48 PM.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Did you include the <stdlib.h> include file?

    In any case, the question is not really about how to fix the error or get around the error (I know how I can avoid it), it is about how to cast to a pointer for array's of size N. fixing the error is more of a side effect.
    Post a small complete program that illustrates your problem. And no fixing the error is not a side effect, it is a requirement.

    You should not be casting the return value of malloc() this cast can mask serious problems, if the program doesn't compile without the cast then you're doing something seriously wrong.

    Jim

  9. #9
    Registered User
    Join Date
    Jan 2016
    Posts
    52
    Quote Originally Posted by jimblumberg View Post
    Did you include the <stdlib.h> include file?
    yes I have it included.

    Quote Originally Posted by jimblumberg View Post
    Post a small complete program that illustrates your problem.
    Code:
    #include <stdlib.h>
    
    int main (int argc, char *argv[]) {
        int *test[5];
        test = malloc(sizeof(test[5])*10);
        free(test);
    }
    and here is the compilation log:
    Code:
    $ gcc -o test test.c
    test.c: In function ‘main’:
    test.c:7: error: incompatible types when assigning to type ‘int *[5]’ from type ‘void *’
    Quote Originally Posted by jimblumberg View Post
    And no fixing the error is not a side effect, it is a requirement.
    I think you misunderstand what I mean. The question "what pointer cast do I use?" is purely an educational question, I could theoretically ask this question without writing a single line of code. Of course in implementation, obviously my code will not work if it doesn't even compile. In this way it is certainly a requirement. I can, and know, how to rewrite my code to avoid this problem with the type cast but I am curious as to what the cast should be. In this way, my question is leaning towards purely educational, with a real world application.

    Quote Originally Posted by jimblumberg View Post
    You should not be casting the return value of malloc() this cast can mask serious problems, if the program doesn't compile without the cast then you're doing something seriously wrong.

    Jim
    This is new to me, even with other compilers I have used, not casting malloc gives a compiler warning, granted I usually ignore it but this seems to suggest that I should be casting the return.

    Would you mind providing some situations where casting is a bad idea here?

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Firstly, wouldn't this give me an array of 2 int pointers? I want a pointer to int arrays of size 2

    cdecl.org says:
    int (*data)[2]
    declare data as pointer to array 2 of int

    Code:
    int (*data)[2] = malloc(sizeof *data);
    Would you mind providing some situations where casting is a bad idea here?
    All of them?
    Optimize memory management
    FAQ > Casting malloc - Cprogramming.com

  11. #11
    Registered User
    Join Date
    Jan 2016
    Posts
    52
    Quote Originally Posted by whiteflags View Post

    cdecl.org says:
    int (*data)[2]
    declare data as pointer to array 2 of int

    Code:
    int (*data)[2] = malloc(sizeof *data);
    Would data[2] be out of bounds? if so, this is not what I want.

  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
    > Would data[2] be out of bounds? if so, this is not what I want.
    Yes it would, and I've no idea now what you want.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define ASIZE 10
    
    void foo ( ) {
      // cdecl> explain int (*data)[2];
      // declare data as pointer to array 2 of int
      int (*data)[2];
      data = malloc( sizeof(*data) * ASIZE );
    
      // the minor dimension is fixed at 2, but you
      // can have as many of the major dimension as
      // you malloc.
      for ( int i = 0 ; i < ASIZE ; i++ ) {
        data[i][0] = 0;
        data[i][1] = 1;
      }
    
      free(data);
    }
    void bar ( ) {
      // cdecl> explain int *data[2];
      // declare data as array 2 of pointer to int
      int *data[2];
      data[0] = malloc( sizeof(*data[0]) * ASIZE );
      data[1] = malloc( sizeof(*data[1]) * ASIZE );
    
      // the major dimension is fixed at 2, but you
      // can have as many of the minor dimension as
      // you malloc.
      for ( int i = 0 ; i < ASIZE ; i++ ) {
        data[0][i] = 0;
        data[1][i] = 1;
      }
    
      free(data[0]);
      free(data[1]);
    }
    
    int main ( ) {
      foo();
      bar();
      return 0;
    }
    
    
    $ gcc -std=c99 -Wall -Wextra -g foo.c
    $ valgrind ./a.out
    ==3976== Memcheck, a memory error detector
    ==3976== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
    ==3976== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
    ==3976== Command: ./a.out
    ==3976== 
    ==3976== 
    ==3976== HEAP SUMMARY:
    ==3976==     in use at exit: 0 bytes in 0 blocks
    ==3976==   total heap usage: 3 allocs, 3 frees, 160 bytes allocated
    ==3976== 
    ==3976== All heap blocks were freed -- no leaks are possible
    ==3976== 
    ==3976== For counts of detected and suppressed errors, rerun with: -v
    ==3976== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
    > Would you mind providing some situations where casting is a bad idea here?
    Yes, in older versions of C, omitting the inclusion of stdlib.h would leave malloc without a prototype - at which point the compiler would automatically assume malloc returned an int. On machines where pointers have different size to int (or machines which use different registers for different types), the code is invisibly broken because the cast hides the error.

    int *test[5];
    test = malloc(sizeof(test[5])*10);
    free(test);

    and here is the compilation log:
    $ gcc -o test test.c
    test.c: In function ‘main’:
    test.c:7: error: incompatible types when assigning to type ‘int *[5]’ from type ‘void *’
    The error is because you can't assign an array in C.
    test[0] = malloc.... is valid
    test = malloc is NOT valid
    You can't synthesise int test[5][10] from int *test[5] with a single call to malloc.

    int (*test)[10] = malloc(5 * sizeof(*test) ); synthesises int test[5][10], but it only works if the minor dimension is a compile time constant.
    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. Replies: 4
    Last Post: 08-18-2015, 03:13 PM
  2. Casting a pointer to char to a pointer to int
    By kkk in forum C Programming
    Replies: 5
    Last Post: 05-18-2011, 11:54 AM
  3. Casting from a 1D array pointer to a scalar pointer
    By komkamol in forum C Programming
    Replies: 8
    Last Post: 09-25-2009, 01:44 AM
  4. Casting to pointer to pointer to void
    By Sharke in forum C Programming
    Replies: 13
    Last Post: 05-12-2009, 08:40 PM
  5. Pointer casting?
    By cpjust in forum C Programming
    Replies: 8
    Last Post: 11-09-2007, 09:55 AM

Tags for this Thread