Thread: 2D array create using malloc: error - invalid type argument of unary *

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    87

    2D array create using malloc: error - invalid type argument of unary *

    Hi Members,

    I'm new to 2D pointers, and C. I'm trying few basic things, of creating new pointer, printing, adding matrices.
    Below is my code:

    Code:
    int main(){
    
      int (*add)[3]=malloc(3*3*sizeof(int));
      int i=0,j=0;
      int mat1[3][3]={{2,3,70},{20,-8,90},{40,-2,-1}};
      int mat2[3][3]={{8,17,-30},{80,12,-10},{-20,-8,100}};
      printf("Initialized 2 matrices\n");
    
      for(i=0;i<=2;i++){
        for(j=0;j<=2;j++){
          *(*(add+i)+j) = mat1[i][j]+mat2[i][j];
        }
      }
    
      for(i=0;i<=2;i++){
    
        for(j=0;j<=2;j++){
    
          printf("%d\t",*(*(add+i)+j));
        }
        printf("\n");
      }
      return 0;
    }
    I get the desired output from this, if I keep:
    int (*add)[3]=malloc(3*3*sizeof(int));

    If I use:

    int *add=malloc(3*3*sizeof(int));
    I get error as:

    matrix_add.c:14: error: invalid type argument of ‘unary *’ (have ‘int’)
    Why is so?
    with *add=malloc(3*3*sizeof(int)); do I not get a pointer in contiguous memory?

    (*add)[3]=malloc(3*3*sizeof(int)); this is same as creating a 2D pointer.

    Please enlighten.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This is error prone:
    Code:
    int (*add)[3]=malloc(3*3*sizeof(int));
    add is a pointer to an array of 3 ints. If you want to allocate space for 3 such arrays of 3 ints, then you should write:
    Code:
    int (*add)[3] = malloc(3 * sizeof(*add));
    Quote Originally Posted by deathmetal
    If I use:

    int *add=malloc(3*3*sizeof(int));
    I get error as:
    [code]matrix_add.c:14: error: invalid type argument of ‘unary *’ (have ‘int’)
    Why is so?
    Since add is now a pointer to an int, *(*(add+i)+j) no longer makes sense. The compiler is basically complaining that you are trying to dereference an int.

    Quote Originally Posted by deathmetal
    with *add=malloc(3*3*sizeof(int)); do I not get a pointer in contiguous memory?
    You do get a pointer that points to the start of a block of contiguous memory (unless malloc returns a null pointer), but that is not the issue. The issue is that if add is a pointer to an int, *(*(add+i)+j) is invalid syntax.

    By the way, there is no point writing *(*(add+i)+j). Just write: add[i][j].
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Quote Originally Posted by laserlight View Post
    This is error prone:
    Code:
    int (*add)[3]=malloc(3*3*sizeof(int));
    add is a pointer to an array of 3 ints. If you want to allocate space for 3 such arrays of 3 ints, then you should write:
    Code:
    int (*add)[3] = malloc(3 * sizeof(*add));

    Since add is now a pointer to an int, *(*(add+i)+j) no longer makes sense. The compiler is basically complaining that you are trying to dereference an int.


    You do get a pointer that points to the start of a block of contiguous memory (unless malloc returns a null pointer), but that is not the issue. The issue is that if add is a pointer to an int, *(*(add+i)+j) is invalid syntax.

    By the way, there is no point writing *(*(add+i)+j). Just write: add[i][j].
    Hi laserlight,

    - Thanks for your attention to my post and correcting the 3*3 malloc part. I was oblivious of it.
    - I could have used
    add[i][j]

    But I was trying to use pointer. Perhaps playing/messing around with it.
    I'd need more understanding here:

    *(*(add+i)+j)=mat1[i][j]+mat2[i][j]
    Doesn't this mean that value at add[i][j] = sum of matrix1 and matrix2's respective row and column value?
    I can print value as printf("%d",*(*(add+i)+j));

    Sorry for my naive doubts.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by deathmetal
    Doesn't this mean that value at add[i][j] = sum of matrix1 and matrix2's respective row and column value?
    Yes.

    Another thing. This is not conventional:
    Code:
    for(i=0;i<=2;i++){
    You should write:
    Code:
    for (i = 0; i < 3; i++) {
    especially since the magic number 3 could be a named constant instead.

    Oh, and remember to check the return value of malloc, and then to free what you malloc.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Hi Laser light,
    Thanks for your comments.

    Quote Originally Posted by laserlight View Post
    Oh, and remember to check the return value of malloc, and then to free what you malloc.
    Code:
    int (*add)[3]=malloc(3*sizeof(int));
    
      if(add==NULL){
        printf("Not succeeded\n");
        exit(-1);
      }
    /*
    *I used above code to check ..
    */
    //But I'm unable to free the allocated memory..
    free(add); //spits *** glibc detected ***
    I'm having hard time to free this memory.

    I used loop to free the memory too, but seems compiler is still complaining.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Post the smallest and simplest program that demonstrates the problem.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Quote Originally Posted by laserlight View Post
    Post the smallest and simplest program that demonstrates the problem.
    Hello laserlight,

    Please see code below:

    Code:
    int main(){
    
      int (*add)[3]=malloc(3*sizeof(int));
      int count=0,i=0,j=0;
    
      if(add != NULL){
        printf ("awesome\n");
    
      }
      else{
        printf("No memory\n");
        exit(-1);
      }
      for(i=0;i<3;i++){
        for(j=0;j<3;j++){
          add[i][j]=count++;
        }
      }
    
      for(i=0;i<3;i++){
        free(*(add+i));
      }
      free(add);
      return 0;
    }
    Error:

    *** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0000000000601010 ***
    Last edited by deathmetal; 08-03-2015 at 12:15 PM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The problem lies with this loop:
    Code:
      for(i=0;i<3;i++){
        free(*(add+i));
      }
    Observe that you called malloc once. So, why do you call free in a loop?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Quote Originally Posted by laserlight View Post
    The problem lies with this loop:
    Code:
      for(i=0;i<3;i++){
        free(*(add+i));
      }
    Observe that you called malloc once. So, why do you call free in a loop?
    Hi,
    Thanks for pointing it.

    If I don't use the loop, I get the same error, of libc.
    How do I free 2D array's pointer?

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by deathmetal
    If I don't use the loop, I get the same error, of libc.
    Oh, I see. You also wrote:
    Code:
    int (*add)[3]=malloc(3*sizeof(int));
    The above is wrong. Basically, whenever you do sizeof(X), where X is a type, you run the risk of using the wrong type. This is exactly what happened here. Refer to my post #2 for a superior alternative.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Quote Originally Posted by laserlight View Post
    The above is wrong. Basically, whenever you do sizeof(X), where X is a type, you run the risk of using the wrong type. This is exactly what happened here. Refer to my post #2 for a superior alternative.
    Hi,
    Ouch, that was too picky.
    int (*add)[3]=malloc(3*sizeof(*add));
    This worked. Thanks.

    But I never read anything like this, before.
    I mean, *add is being assigned memory of *add, weird, isn't it? *add is not created.
    I'm lost.

    Of course, I'm not trying to counter you, but trying to understand the subtleties of pointers.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by deathmetal
    I mean, *add is being assigned memory of *add, weird, isn't it? *add is not created.
    The key lies with understanding sizeof:
    Quote Originally Posted by C11 Clause 6.5.3.4 Paragraph 2
    The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
    So, in sizeof(*add), we see that (*add) is an expression. The type of add is pointer to an array of 3 ints, so the type of *add is an array of 3 ints, hence the type of (*add) is also an array of 3 ints. Therefore, the type of the operand is not a variable length array type, so the operand is not evaluated. Hence, we can validly write sizeof(*add) even though at that point add does not point to anything.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Oct 2013
    Posts
    87
    Thanks much for your patience, and replies to answer my queries. Never seen someone with this depth of knowledge and concepts.
    Looking at your answers, and building upon them, implies most of the code on 2D arrays, malloc; out there is incorrect.!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ERROR, invalide type argument of unary.
    By Tasso Luz in forum C Programming
    Replies: 4
    Last Post: 05-06-2014, 04:38 AM
  2. error:incompatible type for argument 1
    By Hessam in forum C Programming
    Replies: 2
    Last Post: 04-25-2012, 04:33 AM
  3. Invalid type of unary '*'
    By trishaxxcore in forum C Programming
    Replies: 5
    Last Post: 01-24-2010, 12:44 AM
  4. fseek failing - Error: Invalid argument
    By avi2886 in forum C Programming
    Replies: 14
    Last Post: 05-14-2009, 08:49 PM
  5. invalid type argument of `->'
    By BianConiglio in forum C Programming
    Replies: 2
    Last Post: 05-19-2005, 12:57 AM

Tags for this Thread