Thread: Malloc, Pointers, and Structs

  1. #1
    Not just a squid...
    Join Date
    Sep 2004
    Posts
    25

    Malloc, Pointers, and Structs

    It's been a while since I've had to use C, and I'm getting a warning that I can't figure out regarding a dynamic array of structs. Here's an example of the situation I've got (not real variable names in the first struct, and not as many, but otherwise identical to the set-up I'm using):

    Code:
    typedef struct {
         int a;                                                                        
         int b;
         int c;
         char *string1;                                                                  
         char *string2;
    } *Line;                                                   
    
            
    typedef struct {                                                                           
         int nextAvailIndex;
         int maxRows;
         Line *tableRows;  /* this is a pointer to dynamic array of Lines */                                                           
    } *Table;
    The above info is in a .h file to include, in its corresponding .c I have a new_table function that looks like this:

    Code:
    Table new_table(int numRows)
    {
        Table t = (Table) malloc (sizeof (Table));
    
        t -> tableRows = (Line) malloc (sizeof (Line) * numRows);
        t -> nextAvailIndex = 0;
        t -> maxRows = size;
        return t;
     }
    The problem I'm having is that the green line compiles fine, but for the red line I get:
    Code:
    warning: assignment from incompatible pointer type
    I can fix the warning by changing the red line to:
    Code:
    *t -> tableRows = (Line) malloc (sizeof (Line) * numRows);
    Or I can remove the (Line) and (Table) casts from in front of the mallocs and still compile without problems. The first fix of adding * just doesn't look right to me, and I'm afraid I don't remember enough to understand why I wouldn't have to cast the pointers in the second fix. Any suggestions would be great.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    This doesn't look right to me:
    Code:
    } *Line; 
    } *Table;
    Then after you fix that you will want to either a) declare t as a pointer to a Table; or b) use "dot" notation instread of indirect notation.
    Code:
    t.tableRows =
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Not just a squid...
    Join Date
    Sep 2004
    Posts
    25
    Isn't this:

    Code:
    typedef struct {
        /* blah blah blah */
     } *Line;                                                   
        
    typedef struct {                                                                           
        /* blah blah blah */                                                          
    } *Table;
    The same as this:

    Code:
    struct {
        /* blah blah blah */
     } Line;                                                   
        
    struct {                                                                           
        /* blah blah blah */                                                          
    } Table;
    
    typedef struct Line *LinePtr;
    typedef struct Table *TablePtr;
    Maybe I will go with that second way. But I think I need to keep these as pointers to structs rather than structs.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    1. Your casts are redundant, as well as being wrong.
    If you just deleted them, you'd make more progress.

    2. typedef'ing a pointer to a type is more trouble than it's worth.
    Is it really worth having a separate type name just to hide a single * ?
    Such typedef's tend to hide problems more than anything else.
    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.

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Table::tableRows is of type Line *. But here you're casting to just plain Line, not Line*:
    Code:
    t -> tableRows = (Line) malloc (sizeof (Line) * numRows);
    Clearly, something's wrong there, which is what the compiler is telling you. Perhaps you meant to declare tableRows as a Line rather than of type Line*.

    I make a habit not to hide pointers in typedefs, because it makes things so much more confusing.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by TheSquid View Post
    Isn't this:

    The same as this:
    No. In the first case you are creating a typdef'd pointer. An instance of "Line" will be a pointer to a struct. I didn't even know this was legal, probably because no one does it. The reason no one does it is that it is silly, which maybe you will understand why shortly.

    In the second case you have defined a struct. So an instance of "Line" will be a struct, not a pointer to a struct.

    But I think I need to keep these as pointers to structs rather than structs.
    You are confused. Here's the explanation: an instance of a datatype and it's definition are not the same thing. If you want a pointer to an instance of datatype Line, you declare it like any other pointer:
    Code:
    Line *X;   /* for the typedef */
    struct Line *X; /* for the struct version */
    There is your instance of a pointer. This is the normative way; there is no possible purpose in typedefing Line to be a pointer. Remember, if you have a datatype, you can declare either a pointer to it, or an actual instance -- but if that datatype was defined as a pointer, the "instance" is a pointer, so you cannot declare, eg, a local stack instance of the datatype.

    You may think you won't want or need to do that, but you may as well leave the option open, it makes no difference. Also, it is better to use the normal syntax if you are going to be posting code on a forum, since nonsensical, idiosyncratic constructs are just a hassle for others and, conversely, make the code other people write harder for you to understand because of your pointless idiosyncracies (no offence intended!) As Salem wrote:
    Quote Originally Posted by Salem View Post
    2. typedef'ing a pointer to a type is more trouble than it's worth.
    Is it really worth having a separate type name just to hide a single * ?
    Such typedef's tend to hide problems more than anything else.

    Make sense?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by MK27
    No. In the first case you are creating a typdef'd pointer. An instance of "Line" will be a pointer to a struct. I didn't even know this was legal, probably because no one does it. The reason no one does it is that it is silly, which maybe you will understand why shortly.

    In the second case you have defined a struct. So an instance of "Line" will be a struct, not a pointer to a struct.
    No, he's right. They are the same in that "Line" is declared as a pointer to the struct both ways (although they are named differently). The only difference is that the first method hides the name of the struct itself (it is anonymous). In the second case, "LinePtr" will be a pointer -- just like the first case.

    EDIT: I just wanted to reiterate the advice everyone has given that it is a very bad idea to hide pointers behind typedefs. It will hide errors, and cause confusion (as we have already seen in this thread).
    Last edited by bithub; 09-15-2009 at 10:37 AM.
    bit∙hub [bit-huhb] n. A source and destination for information.

  8. #8
    Not just a squid...
    Join Date
    Sep 2004
    Posts
    25
    Quote Originally Posted by MK27 View Post
    Make sense?
    That does make sense.

    Thanks everyone, I'll make some changes and see if I can get it working.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by bithub View Post
    No, he's right. They are the same in that "Line" is declared as a pointer to the struct both ways (although they are named differently). The only difference is that the first method hides the name of the struct itself (it is anonymous). In the second case, "LinePtr" will be a pointer -- just like the first case.
    Hmph. Check that. I thought it would be the same thing as:
    Code:
    struct Line { };
    but no, like I said I don't think I've seen this one before (or if I did I didn't notice the difference!).

    Anyway. Still not a good practice, seems to be the consensus.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Structs, pointers and functions
    By osici in forum C Programming
    Replies: 2
    Last Post: 04-29-2009, 12:35 AM
  2. passing structs & pointers to structs as arguments
    By Markallen85 in forum C Programming
    Replies: 6
    Last Post: 03-16-2004, 07:14 PM
  3. pointers to pointers within structs
    By Lord_azrael99 in forum C Programming
    Replies: 2
    Last Post: 08-28-2003, 04:29 AM
  4. array of pointers to structs
    By stumon in forum C Programming
    Replies: 7
    Last Post: 03-24-2003, 07:13 AM
  5. structs like pointers?
    By mart_man00 in forum C Programming
    Replies: 5
    Last Post: 03-14-2003, 03:16 AM