Array of pointers in a struct

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • fix

    #1

    Array of pointers in a struct

    Hi all,
    I feel unclear about what my code is doing, although it works but I am
    not sure if there is any possible bug, please help me to verify it.
    This is a trie node (just similar to tree nodes) struct, I am storing an
    array of 27 pointers and a void pointer that can point to anything.
    typedef struct trieNode
    {
    struct trieNode *children[27]; // The children nodes
    void *obj; // The object stored
    } TrieNode;

    And this is the code I make a new trie node, initialize and return it.
    TrieNode *newTrieNode()
    {
    int i;
    // Allocate memory for the node
    TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));
    // points the object to NULL
    node->obj = NULL;
    // **********
    *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);
    // Set all pointers in the children array to NULL
    for (i = 0; i < 27; i++)
    node->children[i] = NULL;
    return node;
    }
    The problem comes from the line below the asterisks.
    Initially I have coded
    node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);
    but the compiler does not let me compile.
    When I change it to the one now, it works, but it seems a bit unnatural
    to me. children is a pointer to pointer right? Does *children or
    children[0] have to be initialized by me?
    Thanks.
    fix.

  • Karthik

    #2
    Re: Array of pointers in a struct

    fix wrote:[color=blue]
    > Hi all,
    > I feel unclear about what my code is doing, although it works but I am
    > not sure if there is any possible bug, please help me to verify it.
    > This is a trie node (just similar to tree nodes) struct, I am storing an
    > array of 27 pointers and a void pointer that can point to anything.
    > typedef struct trieNode
    > {
    > struct trieNode *children[27]; // The children nodes
    > void *obj; // The object stored
    > } TrieNode;
    >
    > And this is the code I make a new trie node, initialize and return it.
    > TrieNode *newTrieNode()
    > {
    > int i;
    > // Allocate memory for the node
    > TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]
    This has been beaten to death. This cast is not necessary - Do this
    necessary.

    TrieNode *node = malloc(sizeof(T rieNode));.
    [color=blue]
    > // points the object to NULL
    > node->obj = NULL;
    > // **********
    > *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]

    Whatz this line doing here . I dont understand the significance.
    What is your objective here ?

    --
    Karthik
    Humans please 'removeme_' for my real email.

    Comment

    • Karthik

      #3
      Re: Array of pointers in a struct

      fix wrote:[color=blue]
      > Hi all,
      > I feel unclear about what my code is doing, although it works but I am
      > not sure if there is any possible bug, please help me to verify it.
      > This is a trie node (just similar to tree nodes) struct, I am storing an
      > array of 27 pointers and a void pointer that can point to anything.
      > typedef struct trieNode
      > {
      > struct trieNode *children[27]; // The children nodes
      > void *obj; // The object stored
      > } TrieNode;
      >
      > And this is the code I make a new trie node, initialize and return it.
      > TrieNode *newTrieNode()
      > {
      > int i;
      > // Allocate memory for the node
      > TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]
      This has been beaten to death. This cast is not necessary - Do this
      necessary.

      TrieNode *node = malloc(sizeof(T rieNode));.
      [color=blue]
      > // points the object to NULL
      > node->obj = NULL;
      > // **********
      > *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]

      Whatz this line doing here . I dont understand the significance.
      What is your objective here ?

      --
      Karthik
      Humans please 'removeme_' for my real email.

      Comment

      • Barry Schwarz

        #4
        Re: Array of pointers in a struct

        On Fri, 30 Apr 2004 20:47:47 -0500, fix <fix@here.com > wrote:
        [color=blue]
        >Hi all,
        >I feel unclear about what my code is doing, although it works but I am
        >not sure if there is any possible bug, please help me to verify it.
        >This is a trie node (just similar to tree nodes) struct, I am storing an
        >array of 27 pointers and a void pointer that can point to anything.
        >typedef struct trieNode
        >{
        > struct trieNode *children[27]; // The children nodes[/color]

        This is an array of 27 pointers.
        [color=blue]
        > void *obj; // The object stored
        >} TrieNode;
        >
        >And this is the code I make a new trie node, initialize and return it.
        >TrieNode *newTrieNode()
        >{
        > int i;
        > // Allocate memory for the node
        > TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]

        Don't cast the return from malloc. It doesn't help and can prevent
        the compiler from warning you that you forgot to include stdlib.h.
        Such an omission would lead to undefined behavior.
        [color=blue]
        > // points the object to NULL
        > node->obj = NULL;
        > // **********
        > *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]

        This is a problem. Work through the types.

        node is a pointer to struct.
        node->children is an array of 27 pointers to struct.
        *(node->children) is exactly equivalent to (node->children)[0]
        which is the first element of that array. This element is obviously a
        pointer to struct.
        The space you allocate is not sufficient to hold such a struct.
        The struct consists of 27 struct pointers plus a void pointer plus any
        padding. You allocate only enough space for the 27 struct pointers.
        At this point you have committed the unpardonable sin of lying to
        the compiler. You have told it that node->children[0] will point to
        a struct and it doesn't.

        On top of all that, you don't need this code. The struct already
        contains an array of 27 pointers so you don't need another set.
        [color=blue]
        > // Set all pointers in the children array to NULL
        > for (i = 0; i < 27; i++)
        > node->children[i] = NULL;[/color]

        The first time through the loop, you destroy the value in
        node->children[0] that you set in the previous malloc. This causes a
        memory leak because you can never recover the original address to free
        the memory.
        [color=blue]
        > return node;
        >}
        >The problem comes from the line below the asterisks.
        >Initially I have coded
        >node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);[/color]

        Work through the types as above. node->children is an array. An
        unsubscripted array may not appear on the left of an assignment
        statement. (It is not a modifiable lvalue.)

        As noted above you don't need this either. node->children already
        contains enough space to hold 27 pointers to struct.
        [color=blue]
        >but the compiler does not let me compile.
        >When I change it to the one now, it works, but it seems a bit unnatural
        >to me. children is a pointer to pointer right? Does *children or
        >children[0] have to be initialized by me?[/color]

        Yes. In your very first malloc (the one just with node), you allocate
        space to hold the struct. The struct consists of 28 variables, 27
        pointers to struct and 1 pointer to void. You must initialize each of
        these variables before it is evaluated. That means children[0],
        children[1], ..., children[26]. You do initialize the pointer to void
        above.

        When you do initialize one of the children, it must be with NULL or
        with the address of a struct (or dynamically allocated memory large
        enough to hold a struct).



        <<Remove the del for email>>

        Comment

        • fix

          #5
          Re: Array of pointers in a struct



          Barry Schwarz wrote:[color=blue][color=green]
          >> struct trieNode *children[27]; // The children nodes[/color]
          >
          >
          > This is an array of 27 pointers.[/color]

          Yes.
          [color=blue][color=green]
          >>And this is the code I make a new trie node, initialize and return it.
          >>TrieNode *newTrieNode()
          >>{
          >> int i;
          >> // Allocate memory for the node
          >> TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]
          >
          >
          > Don't cast the return from malloc. It doesn't help and can prevent
          > the compiler from warning you that you forgot to include stdlib.h.
          > Such an omission would lead to undefined behavior.[/color]

          I did read post about this problem. I would like to omit it if possible.
          Well I am using VS.NET to write the programs, test and compile, if I
          cast it, there's a warning, if I don't, there isn't.
          But the problem is, these programs are assignment of my computer science
          class, and the prof said that I have to make sure it works on gcc. gcc
          does give me error if I don't cast:
          warning: initialization makes pointer from integer without a cast
          if I cast, it doesn't give me this.
          I did turn in my first C program without any cast, I got marks deduced.
          [color=blue][color=green]
          >> // **********
          >> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]
          >
          >
          > This is a problem. Work through the types.
          >
          > node is a pointer to struct.
          > node->children is an array of 27 pointers to struct.
          > *(node->children) is exactly equivalent to (node->children)[0]
          > which is the first element of that array. This element is obviously a
          > pointer to struct.
          > The space you allocate is not sufficient to hold such a struct.
          > The struct consists of 27 struct pointers plus a void pointer plus any
          > padding. You allocate only enough space for the 27 struct pointers.
          > At this point you have committed the unpardonable sin of lying to
          > the compiler. You have told it that node->children[0] will point to
          > a struct and it doesn't.
          >
          > On top of all that, you don't need this code. The struct already
          > contains an array of 27 pointers so you don't need another set.[/color]

          Hm...... I am not that clear about what I learnt. A var[] and *var can
          be used interchangeably , but what's the difference? Does the compiler
          allocate space for var[] but not *var?
          [color=blue][color=green]
          >> // Set all pointers in the children array to NULL
          >> for (i = 0; i < 27; i++)
          >> node->children[i] = NULL;[/color]
          >
          >
          > The first time through the loop, you destroy the value in
          > node->children[0] that you set in the previous malloc. This causes a
          > memory leak because you can never recover the original address to free
          > the memory.[/color]

          Well actually if I don't free() the memory I allocated, will the memory
          be free after the program quits?
          [color=blue][color=green]
          >> return node;
          >>}
          >>The problem comes from the line below the asterisks.
          >>Initially I have coded
          >>node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);[/color]
          >
          >
          > Work through the types as above. node->children is an array. An
          > unsubscripted array may not appear on the left of an assignment
          > statement. (It is not a modifiable lvalue.)[/color]

          Oh that's the error when I compiled. "left operand must be l-value", I
          didn't really understand what it means.
          [color=blue]
          > As noted above you don't need this either. node->children already
          > contains enough space to hold 27 pointers to struct.
          >
          >[color=green]
          >>but the compiler does not let me compile.
          >>When I change it to the one now, it works, but it seems a bit unnatural
          >>to me. children is a pointer to pointer right? Does *children or
          >>children[0] have to be initialized by me?[/color]
          >
          >
          > Yes. In your very first malloc (the one just with node), you allocate
          > space to hold the struct. The struct consists of 28 variables, 27
          > pointers to struct and 1 pointer to void. You must initialize each of
          > these variables before it is evaluated. That means children[0],
          > children[1], ..., children[26]. You do initialize the pointer to void
          > above.
          >
          > When you do initialize one of the children, it must be with NULL or
          > with the address of a struct (or dynamically allocated memory large
          > enough to hold a struct).[/color]

          So I did right in the for-loop?

          Comment

          • Barry Schwarz

            #6
            Re: Array of pointers in a struct

            On Fri, 30 Apr 2004 20:47:47 -0500, fix <fix@here.com > wrote:
            [color=blue]
            >Hi all,
            >I feel unclear about what my code is doing, although it works but I am
            >not sure if there is any possible bug, please help me to verify it.
            >This is a trie node (just similar to tree nodes) struct, I am storing an
            >array of 27 pointers and a void pointer that can point to anything.
            >typedef struct trieNode
            >{
            > struct trieNode *children[27]; // The children nodes[/color]

            This is an array of 27 pointers.
            [color=blue]
            > void *obj; // The object stored
            >} TrieNode;
            >
            >And this is the code I make a new trie node, initialize and return it.
            >TrieNode *newTrieNode()
            >{
            > int i;
            > // Allocate memory for the node
            > TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]

            Don't cast the return from malloc. It doesn't help and can prevent
            the compiler from warning you that you forgot to include stdlib.h.
            Such an omission would lead to undefined behavior.
            [color=blue]
            > // points the object to NULL
            > node->obj = NULL;
            > // **********
            > *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]

            This is a problem. Work through the types.

            node is a pointer to struct.
            node->children is an array of 27 pointers to struct.
            *(node->children) is exactly equivalent to (node->children)[0]
            which is the first element of that array. This element is obviously a
            pointer to struct.
            The space you allocate is not sufficient to hold such a struct.
            The struct consists of 27 struct pointers plus a void pointer plus any
            padding. You allocate only enough space for the 27 struct pointers.
            At this point you have committed the unpardonable sin of lying to
            the compiler. You have told it that node->children[0] will point to
            a struct and it doesn't.

            On top of all that, you don't need this code. The struct already
            contains an array of 27 pointers so you don't need another set.
            [color=blue]
            > // Set all pointers in the children array to NULL
            > for (i = 0; i < 27; i++)
            > node->children[i] = NULL;[/color]

            The first time through the loop, you destroy the value in
            node->children[0] that you set in the previous malloc. This causes a
            memory leak because you can never recover the original address to free
            the memory.
            [color=blue]
            > return node;
            >}
            >The problem comes from the line below the asterisks.
            >Initially I have coded
            >node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);[/color]

            Work through the types as above. node->children is an array. An
            unsubscripted array may not appear on the left of an assignment
            statement. (It is not a modifiable lvalue.)

            As noted above you don't need this either. node->children already
            contains enough space to hold 27 pointers to struct.
            [color=blue]
            >but the compiler does not let me compile.
            >When I change it to the one now, it works, but it seems a bit unnatural
            >to me. children is a pointer to pointer right? Does *children or
            >children[0] have to be initialized by me?[/color]

            Yes. In your very first malloc (the one just with node), you allocate
            space to hold the struct. The struct consists of 28 variables, 27
            pointers to struct and 1 pointer to void. You must initialize each of
            these variables before it is evaluated. That means children[0],
            children[1], ..., children[26]. You do initialize the pointer to void
            above.

            When you do initialize one of the children, it must be with NULL or
            with the address of a struct (or dynamically allocated memory large
            enough to hold a struct).



            <<Remove the del for email>>

            Comment

            • fix

              #7
              Re: Array of pointers in a struct



              Barry Schwarz wrote:[color=blue][color=green]
              >> struct trieNode *children[27]; // The children nodes[/color]
              >
              >
              > This is an array of 27 pointers.[/color]

              Yes.
              [color=blue][color=green]
              >>And this is the code I make a new trie node, initialize and return it.
              >>TrieNode *newTrieNode()
              >>{
              >> int i;
              >> // Allocate memory for the node
              >> TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]
              >
              >
              > Don't cast the return from malloc. It doesn't help and can prevent
              > the compiler from warning you that you forgot to include stdlib.h.
              > Such an omission would lead to undefined behavior.[/color]

              I did read post about this problem. I would like to omit it if possible.
              Well I am using VS.NET to write the programs, test and compile, if I
              cast it, there's a warning, if I don't, there isn't.
              But the problem is, these programs are assignment of my computer science
              class, and the prof said that I have to make sure it works on gcc. gcc
              does give me error if I don't cast:
              warning: initialization makes pointer from integer without a cast
              if I cast, it doesn't give me this.
              I did turn in my first C program without any cast, I got marks deduced.
              [color=blue][color=green]
              >> // **********
              >> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]
              >
              >
              > This is a problem. Work through the types.
              >
              > node is a pointer to struct.
              > node->children is an array of 27 pointers to struct.
              > *(node->children) is exactly equivalent to (node->children)[0]
              > which is the first element of that array. This element is obviously a
              > pointer to struct.
              > The space you allocate is not sufficient to hold such a struct.
              > The struct consists of 27 struct pointers plus a void pointer plus any
              > padding. You allocate only enough space for the 27 struct pointers.
              > At this point you have committed the unpardonable sin of lying to
              > the compiler. You have told it that node->children[0] will point to
              > a struct and it doesn't.
              >
              > On top of all that, you don't need this code. The struct already
              > contains an array of 27 pointers so you don't need another set.[/color]

              Hm...... I am not that clear about what I learnt. A var[] and *var can
              be used interchangeably , but what's the difference? Does the compiler
              allocate space for var[] but not *var?
              [color=blue][color=green]
              >> // Set all pointers in the children array to NULL
              >> for (i = 0; i < 27; i++)
              >> node->children[i] = NULL;[/color]
              >
              >
              > The first time through the loop, you destroy the value in
              > node->children[0] that you set in the previous malloc. This causes a
              > memory leak because you can never recover the original address to free
              > the memory.[/color]

              Well actually if I don't free() the memory I allocated, will the memory
              be free after the program quits?
              [color=blue][color=green]
              >> return node;
              >>}
              >>The problem comes from the line below the asterisks.
              >>Initially I have coded
              >>node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);[/color]
              >
              >
              > Work through the types as above. node->children is an array. An
              > unsubscripted array may not appear on the left of an assignment
              > statement. (It is not a modifiable lvalue.)[/color]

              Oh that's the error when I compiled. "left operand must be l-value", I
              didn't really understand what it means.
              [color=blue]
              > As noted above you don't need this either. node->children already
              > contains enough space to hold 27 pointers to struct.
              >
              >[color=green]
              >>but the compiler does not let me compile.
              >>When I change it to the one now, it works, but it seems a bit unnatural
              >>to me. children is a pointer to pointer right? Does *children or
              >>children[0] have to be initialized by me?[/color]
              >
              >
              > Yes. In your very first malloc (the one just with node), you allocate
              > space to hold the struct. The struct consists of 28 variables, 27
              > pointers to struct and 1 pointer to void. You must initialize each of
              > these variables before it is evaluated. That means children[0],
              > children[1], ..., children[26]. You do initialize the pointer to void
              > above.
              >
              > When you do initialize one of the children, it must be with NULL or
              > with the address of a struct (or dynamically allocated memory large
              > enough to hold a struct).[/color]

              So I did right in the for-loop?

              Comment

              • Mark McIntyre

                #8
                Re: Array of pointers in a struct

                On Sat, 01 May 2004 01:19:14 -0500, in comp.lang.c , fix <fix@here.com >
                wrote:
                [color=blue][color=green]
                >> Don't cast the return from malloc. It doesn't help and can prevent
                >> the compiler from warning you that you forgot to include stdlib.h.
                >> Such an omission would lead to undefined behavior.[/color]
                >
                >But the problem is, these programs are assignment of my computer science
                > class, and the prof said that I have to make sure it works on gcc. gcc
                >does give me error if I don't cast:[/color]

                This is eactly why you _do not_ cast. The warning is to tell you that you
                are doing something wrong. In this case, you have not included the header
                that prototypes malloc. The result is that your code is seriously
                defective, and may even crash.
                [color=blue]
                >warning: initialization makes pointer from integer without a cast[/color]

                This is a serious warning. DO NOT HIDE WARNINGS WITH CASTS until you know
                precisely what you're doing !
                [color=blue]
                >if I cast, it doesn't give me this.[/color]

                Because then you are saying to the compiler "Yes, I want to turn an integer
                into a pointer, even though it is meaningless and produces garbage"

                --
                Mark McIntyre
                CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>


                ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
                http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
                ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

                Comment

                • Barry Schwarz

                  #9
                  Re: Array of pointers in a struct

                  On Sat, 01 May 2004 01:19:14 -0500, fix <fix@here.com > wrote:
                  [color=blue]
                  >
                  >
                  >Barry Schwarz wrote:[color=green][color=darkred]
                  >>> struct trieNode *children[27]; // The children nodes[/color]
                  >>
                  >>
                  >> This is an array of 27 pointers.[/color]
                  >
                  >Yes.
                  >[color=green][color=darkred]
                  >>>And this is the code I make a new trie node, initialize and return it.
                  >>>TrieNode *newTrieNode()
                  >>>{
                  >>> int i;
                  >>> // Allocate memory for the node
                  >>> TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));[/color]
                  >>
                  >>
                  >> Don't cast the return from malloc. It doesn't help and can prevent
                  >> the compiler from warning you that you forgot to include stdlib.h.
                  >> Such an omission would lead to undefined behavior.[/color]
                  >
                  >I did read post about this problem. I would like to omit it if possible.
                  >Well I am using VS.NET to write the programs, test and compile, if I
                  >cast it, there's a warning, if I don't, there isn't.[/color]

                  Go back and read my original comment. Did you include stdlib.h?
                  [color=blue]
                  >But the problem is, these programs are assignment of my computer science
                  > class, and the prof said that I have to make sure it works on gcc. gcc
                  >does give me error if I don't cast:
                  >warning: initialization makes pointer from integer without a cast
                  >if I cast, it doesn't give me this.[/color]

                  This is exactly the warning you need to avoid undefined behavior. The
                  warning tells you the compiler thinks malloc is returning an integer.
                  Since you know malloc returns a pointer to void, the question is why
                  does the compiler think this? The answer is because you never told
                  the compiler what malloc really did. The reason you never told it is
                  because you forgot to include stdlib.h which contains the prototype
                  for malloc.

                  I don't know anything about gcc or your hardware but consider the case
                  where returned pointers and returned integers use different hardware
                  registers. The cast shuts up the warning without solving the problem.
                  All the cast does is tell the compiler to generate code that takes the
                  supposed integer return from malloc and convert it without warning to
                  a pointer. Since malloc doesn't return an integer, this still makes
                  no sense.
                  [color=blue]
                  >I did turn in my first C program without any cast, I got marks deduced.[/color]

                  If you turned in a program with warnings, what do you expect.
                  [color=blue]
                  >[color=green][color=darkred]
                  >>> // **********
                  >>> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);[/color]
                  >>
                  >>
                  >> This is a problem. Work through the types.
                  >>
                  >> node is a pointer to struct.
                  >> node->children is an array of 27 pointers to struct.
                  >> *(node->children) is exactly equivalent to (node->children)[0]
                  >> which is the first element of that array. This element is obviously a
                  >> pointer to struct.
                  >> The space you allocate is not sufficient to hold such a struct.
                  >> The struct consists of 27 struct pointers plus a void pointer plus any
                  >> padding. You allocate only enough space for the 27 struct pointers.
                  >> At this point you have committed the unpardonable sin of lying to
                  >> the compiler. You have told it that node->children[0] will point to
                  >> a struct and it doesn't.
                  >>
                  >> On top of all that, you don't need this code. The struct already
                  >> contains an array of 27 pointers so you don't need another set.[/color]
                  >
                  >Hm...... I am not that clear about what I learnt. A var[] and *var can
                  >be used interchangeably , but what's the difference? Does the compiler
                  >allocate space for var[] but not *var?[/color]

                  NO NO NO NO. A var[] is an array. A *var is a pointer. While they
                  share a certain amount of common syntax using subscript notation they
                  are by no means interchangeable . Read the faq. Look in your text.
                  Google through the archives for postings that talk about pointers and
                  arrays, especially those by CBFalconer.

                  And for heaven's sake, don't say this to your instructor. The only
                  possible result is bad. Either he will downgrade you for not
                  understanding a basic aspect of the language or he will agree with you
                  and you will know he is incompetent and you have wasted a semester.
                  [color=blue]
                  >[color=green][color=darkred]
                  >>> // Set all pointers in the children array to NULL
                  >>> for (i = 0; i < 27; i++)
                  >>> node->children[i] = NULL;[/color]
                  >>
                  >>
                  >> The first time through the loop, you destroy the value in
                  >> node->children[0] that you set in the previous malloc. This causes a
                  >> memory leak because you can never recover the original address to free
                  >> the memory.[/color]
                  >
                  >Well actually if I don't free() the memory I allocated, will the memory
                  >be free after the program quits?[/color]

                  And you believe this is an excuse to write sloppy code?
                  [color=blue]
                  >[color=green][color=darkred]
                  >>> return node;
                  >>>}
                  >>>The problem comes from the line below the asterisks.
                  >>>Initially I have coded
                  >>>node->children = (TrieNode **)malloc(sizeo f(TrieNode *) * 27);[/color]
                  >>
                  >>
                  >> Work through the types as above. node->children is an array. An
                  >> unsubscripted array may not appear on the left of an assignment
                  >> statement. (It is not a modifiable lvalue.)[/color]
                  >
                  >Oh that's the error when I compiled. "left operand must be l-value", I
                  >didn't really understand what it means.
                  >[color=green]
                  >> As noted above you don't need this either. node->children already
                  >> contains enough space to hold 27 pointers to struct.
                  >>
                  >>[color=darkred]
                  >>>but the compiler does not let me compile.
                  >>>When I change it to the one now, it works, but it seems a bit unnatural
                  >>>to me. children is a pointer to pointer right? Does *children or
                  >>>children[0] have to be initialized by me?[/color]
                  >>
                  >>
                  >> Yes. In your very first malloc (the one just with node), you allocate
                  >> space to hold the struct. The struct consists of 28 variables, 27
                  >> pointers to struct and 1 pointer to void. You must initialize each of
                  >> these variables before it is evaluated. That means children[0],
                  >> children[1], ..., children[26]. You do initialize the pointer to void
                  >> above.
                  >>
                  >> When you do initialize one of the children, it must be with NULL or
                  >> with the address of a struct (or dynamically allocated memory large
                  >> enough to hold a struct).[/color]
                  >
                  >So I did right in the for-loop?[/color]

                  Depends on why you want an array of 27 NULL pointers.


                  <<Remove the del for email>>

                  Comment

                  • CBFalconer

                    #10
                    Re: Array of pointers in a struct

                    Barry Schwarz wrote:[color=blue]
                    > On Sat, 01 May 2004 01:19:14 -0500, fix <fix@here.com > wrote:
                    >[/color]
                    .... snip ...[color=blue][color=green]
                    >>
                    >> Hm...... I am not that clear about what I learnt. A var[] and
                    >> *var can be used interchangeably , but what's the difference?
                    >> Does the compiler allocate space for var[] but not *var?[/color]
                    >
                    > NO NO NO NO. A var[] is an array. A *var is a pointer. While
                    > they share a certain amount of common syntax using subscript
                    > notation they are by no means interchangeable . Read the faq.
                    > Look in your text. Google through the archives for postings that
                    > talk about pointers and arrays, especially those by CBFalconer.[/color]

                    I think you mean Chris Torek :-) Look for 'the rule'.

                    --
                    A: Because it fouls the order in which people normally read text.
                    Q: Why is top-posting such a bad thing?
                    A: Top-posting.
                    Q: What is the most annoying thing on usenet and in e-mail?

                    Comment

                    • fix

                      #11
                      Re: Array of pointers in a struct


                      Barry Schwarz wrote:[color=blue][color=green][color=darkred]
                      >>>>And this is the code I make a new trie node, initialize and return it.
                      >>>>TrieNode *newTrieNode()
                      >>>>{
                      >>>> int i;
                      >>>> // Allocate memory for the node
                      >>>> TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));
                      >>>
                      >>>
                      >>>Don't cast the return from malloc. It doesn't help and can prevent
                      >>>the compiler from warning you that you forgot to include stdlib.h.
                      >>>Such an omission would lead to undefined behavior.[/color]
                      >>
                      >>I did read post about this problem. I would like to omit it if possible.
                      >>Well I am using VS.NET to write the programs, test and compile, if I
                      >>cast it, there's a warning, if I don't, there isn't.[/color]
                      >
                      >
                      > Go back and read my original comment. Did you include stdlib.h?[/color]

                      OK, I didn't. But why does my program can still use malloca?
                      [color=blue][color=green]
                      >>But the problem is, these programs are assignment of my computer science
                      >> class, and the prof said that I have to make sure it works on gcc. gcc
                      >>does give me error if I don't cast:
                      >>warning: initialization makes pointer from integer without a cast
                      >>if I cast, it doesn't give me this.[/color]
                      >
                      >
                      > This is exactly the warning you need to avoid undefined behavior. The
                      > warning tells you the compiler thinks malloc is returning an integer.
                      > Since you know malloc returns a pointer to void, the question is why
                      > does the compiler think this? The answer is because you never told
                      > the compiler what malloc really did. The reason you never told it is
                      > because you forgot to include stdlib.h which contains the prototype
                      > for malloc.
                      >
                      > I don't know anything about gcc or your hardware but consider the case
                      > where returned pointers and returned integers use different hardware
                      > registers. The cast shuts up the warning without solving the problem.
                      > All the cast does is tell the compiler to generate code that takes the
                      > supposed integer return from malloc and convert it without warning to
                      > a pointer. Since malloc doesn't return an integer, this still makes
                      > no sense.
                      >
                      >[color=green]
                      >>I did turn in my first C program without any cast, I got marks deduced.[/color]
                      >
                      >
                      > If you turned in a program with warnings, what do you expect.
                      >
                      >[color=green][color=darkred]
                      >>>> // **********
                      >>>> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);
                      >>>
                      >>>
                      >>>This is a problem. Work through the types.
                      >>>
                      >>> node is a pointer to struct.
                      >>> node->children is an array of 27 pointers to struct.
                      >>> *(node->children) is exactly equivalent to (node->children)[0]
                      >>>which is the first element of that array. This element is obviously a
                      >>>pointer to struct.
                      >>> The space you allocate is not sufficient to hold such a struct.
                      >>>The struct consists of 27 struct pointers plus a void pointer plus any
                      >>>padding. You allocate only enough space for the 27 struct pointers.
                      >>> At this point you have committed the unpardonable sin of lying to
                      >>>the compiler. You have told it that node->children[0] will point to
                      >>>a struct and it doesn't.
                      >>>
                      >>>On top of all that, you don't need this code. The struct already
                      >>>contains an array of 27 pointers so you don't need another set.[/color]
                      >>
                      >>Hm...... I am not that clear about what I learnt. A var[] and *var can
                      >>be used interchangeably , but what's the difference? Does the compiler
                      >>allocate space for var[] but not *var?[/color]
                      >
                      >
                      > NO NO NO NO. A var[] is an array. A *var is a pointer. While they
                      > share a certain amount of common syntax using subscript notation they
                      > are by no means interchangeable . Read the faq. Look in your text.
                      > Google through the archives for postings that talk about pointers and
                      > arrays, especially those by CBFalconer.
                      >
                      > And for heaven's sake, don't say this to your instructor. The only
                      > possible result is bad. Either he will downgrade you for not
                      > understanding a basic aspect of the language or he will agree with you
                      > and you will know he is incompetent and you have wasted a semester.[/color]

                      OK, yes, my book says they have "strong relationship". I guess I should
                      study harder...
                      [color=blue][color=green]
                      >>Well actually if I don't free() the memory I allocated, will the memory
                      >>be free after the program quits?[/color]
                      >
                      >
                      > And you believe this is an excuse to write sloppy code?[/color]

                      So is it required to free() the memory I allocated. I didn't do that
                      before unless required.

                      Comment

                      • Barry Schwarz

                        #12
                        Re: Array of pointers in a struct

                        On Sat, 01 May 2004 15:29:50 -0500, fix <fix@here.com > wrote:
                        [color=blue]
                        >
                        >Barry Schwarz wrote:[color=green][color=darkred]
                        >>>>>And this is the code I make a new trie node, initialize and return it.
                        >>>>>TrieNode *newTrieNode()
                        >>>>>{
                        >>>>> int i;
                        >>>>> // Allocate memory for the node
                        >>>>> TrieNode *node = (TrieNode *)malloc(sizeof (TrieNode));
                        >>>>
                        >>>>
                        >>>>Don't cast the return from malloc. It doesn't help and can prevent
                        >>>>the compiler from warning you that you forgot to include stdlib.h.
                        >>>>Such an omission would lead to undefined behavior.
                        >>>
                        >>>I did read post about this problem. I would like to omit it if possible.
                        >>>Well I am using VS.NET to write the programs, test and compile, if I
                        >>>cast it, there's a warning, if I don't, there isn't.[/color]
                        >>
                        >>
                        >> Go back and read my original comment. Did you include stdlib.h?[/color]
                        >
                        >OK, I didn't. But why does my program can still use malloca?[/color]

                        What is malloca?

                        Your program uses malloc because you coded it to. Under C89, if you
                        call a function without a prototype, the compiler assumes that the
                        arguments are the correct type and the function returns an int. It
                        then generates the appropriate clues for the linker to include that
                        function in you program. Since the assumed return type is incorrect
                        for malloc, you have invoked undefined behavior.
                        [color=blue]
                        >[color=green][color=darkred]
                        >>>But the problem is, these programs are assignment of my computer science
                        >>> class, and the prof said that I have to make sure it works on gcc. gcc
                        >>>does give me error if I don't cast:
                        >>>warning: initialization makes pointer from integer without a cast
                        >>>if I cast, it doesn't give me this.[/color]
                        >>
                        >>
                        >> This is exactly the warning you need to avoid undefined behavior. The
                        >> warning tells you the compiler thinks malloc is returning an integer.
                        >> Since you know malloc returns a pointer to void, the question is why
                        >> does the compiler think this? The answer is because you never told
                        >> the compiler what malloc really did. The reason you never told it is
                        >> because you forgot to include stdlib.h which contains the prototype
                        >> for malloc.
                        >>
                        >> I don't know anything about gcc or your hardware but consider the case
                        >> where returned pointers and returned integers use different hardware
                        >> registers. The cast shuts up the warning without solving the problem.
                        >> All the cast does is tell the compiler to generate code that takes the
                        >> supposed integer return from malloc and convert it without warning to
                        >> a pointer. Since malloc doesn't return an integer, this still makes
                        >> no sense.
                        >>
                        >>[color=darkred]
                        >>>I did turn in my first C program without any cast, I got marks deduced.[/color]
                        >>
                        >>
                        >> If you turned in a program with warnings, what do you expect.
                        >>
                        >>[color=darkred]
                        >>>>> // **********
                        >>>>> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);
                        >>>>
                        >>>>
                        >>>>This is a problem. Work through the types.
                        >>>>
                        >>>> node is a pointer to struct.
                        >>>> node->children is an array of 27 pointers to struct.
                        >>>> *(node->children) is exactly equivalent to (node->children)[0]
                        >>>>which is the first element of that array. This element is obviously a
                        >>>>pointer to struct.
                        >>>> The space you allocate is not sufficient to hold such a struct.
                        >>>>The struct consists of 27 struct pointers plus a void pointer plus any
                        >>>>padding. You allocate only enough space for the 27 struct pointers.
                        >>>> At this point you have committed the unpardonable sin of lying to
                        >>>>the compiler. You have told it that node->children[0] will point to
                        >>>>a struct and it doesn't.
                        >>>>
                        >>>>On top of all that, you don't need this code. The struct already
                        >>>>contains an array of 27 pointers so you don't need another set.
                        >>>
                        >>>Hm...... I am not that clear about what I learnt. A var[] and *var can
                        >>>be used interchangeably , but what's the difference? Does the compiler
                        >>>allocate space for var[] but not *var?[/color]
                        >>
                        >>
                        >> NO NO NO NO. A var[] is an array. A *var is a pointer. While they
                        >> share a certain amount of common syntax using subscript notation they
                        >> are by no means interchangeable . Read the faq. Look in your text.
                        >> Google through the archives for postings that talk about pointers and
                        >> arrays, especially those by CBFalconer.
                        >>
                        >> And for heaven's sake, don't say this to your instructor. The only
                        >> possible result is bad. Either he will downgrade you for not
                        >> understanding a basic aspect of the language or he will agree with you
                        >> and you will know he is incompetent and you have wasted a semester.[/color]
                        >
                        >OK, yes, my book says they have "strong relationship". I guess I should
                        >study harder...
                        >[color=green][color=darkred]
                        >>>Well actually if I don't free() the memory I allocated, will the memory
                        >>>be free after the program quits?[/color]
                        >>
                        >>
                        >> And you believe this is an excuse to write sloppy code?[/color]
                        >
                        >So is it required to free() the memory I allocated. I didn't do that
                        >before unless required.[/color]

                        The standard does not specify what the operating system will do when
                        you program terminates. It is never wrong to clean up after your self
                        and on a "not well designed system" it may in fact be necessary. I
                        don't have a clue about whether your system will clean up your mess or
                        not but in this newsgroup we don't depend on system specific behavior.


                        <<Remove the del for email>>

                        Comment

                        • Barry Schwarz

                          #13
                          Re: Array of pointers in a struct

                          On Sat, 01 May 2004 17:52:06 GMT, CBFalconer <cbfalconer@yah oo.com>
                          wrote:
                          [color=blue]
                          >Barry Schwarz wrote:[color=green]
                          >> On Sat, 01 May 2004 01:19:14 -0500, fix <fix@here.com > wrote:
                          >>[/color]
                          >... snip ...[color=green][color=darkred]
                          >>>
                          >>> Hm...... I am not that clear about what I learnt. A var[] and
                          >>> *var can be used interchangeably , but what's the difference?
                          >>> Does the compiler allocate space for var[] but not *var?[/color]
                          >>
                          >> NO NO NO NO. A var[] is an array. A *var is a pointer. While
                          >> they share a certain amount of common syntax using subscript
                          >> notation they are by no means interchangeable . Read the faq.
                          >> Look in your text. Google through the archives for postings that
                          >> talk about pointers and arrays, especially those by CBFalconer.[/color]
                          >
                          >I think you mean Chris Torek :-) Look for 'the rule'.[/color]

                          Sorry about that but at least I did get four of the letters right,
                          though not always in the correct order.


                          <<Remove the del for email>>

                          Comment

                          • fix

                            #14
                            Re: Array of pointers in a struct



                            Barry Schwarz wrote:
                            [color=blue][color=green]
                            >>OK, I didn't. But why does my program can still use malloca?[/color]
                            >
                            >
                            > What is malloca?[/color]

                            It's a typo.
                            [color=blue]
                            > Your program uses malloc because you coded it to. Under C89, if you
                            > call a function without a prototype, the compiler assumes that the
                            > arguments are the correct type and the function returns an int. It
                            > then generates the appropriate clues for the linker to include that
                            > function in you program. Since the assumed return type is incorrect
                            > for malloc, you have invoked undefined behavior.[/color]

                            I meant, I don't include the header and can still call malloc, does the
                            compiler know where to find the actual malloc implementation?
                            [color=blue][color=green][color=darkred]
                            >>>>But the problem is, these programs are assignment of my computer science
                            >>>>class, and the prof said that I have to make sure it works on gcc. gcc
                            >>>>does give me error if I don't cast:
                            >>>>warning: initialization makes pointer from integer without a cast
                            >>>>if I cast, it doesn't give me this.
                            >>>
                            >>>
                            >>>This is exactly the warning you need to avoid undefined behavior. The
                            >>>warning tells you the compiler thinks malloc is returning an integer.
                            >>>Since you know malloc returns a pointer to void, the question is why
                            >>>does the compiler think this? The answer is because you never told
                            >>>the compiler what malloc really did. The reason you never told it is
                            >>>because you forgot to include stdlib.h which contains the prototype
                            >>>for malloc.
                            >>>
                            >>>I don't know anything about gcc or your hardware but consider the case
                            >>>where returned pointers and returned integers use different hardware
                            >>>registers. The cast shuts up the warning without solving the problem.
                            >>>All the cast does is tell the compiler to generate code that takes the
                            >>>supposed integer return from malloc and convert it without warning to
                            >>>a pointer. Since malloc doesn't return an integer, this still makes
                            >>>no sense.
                            >>>
                            >>>
                            >>>
                            >>>>I did turn in my first C program without any cast, I got marks deduced.
                            >>>
                            >>>
                            >>>If you turned in a program with warnings, what do you expect.
                            >>>
                            >>>
                            >>>
                            >>>>>> // **********
                            >>>>>> *(node->children) = (TrieNode *)malloc(sizeof (TrieNode *) * 27);
                            >>>>>
                            >>>>>
                            >>>>>This is a problem. Work through the types.
                            >>>>>
                            >>>>> node is a pointer to struct.
                            >>>>> node->children is an array of 27 pointers to struct.
                            >>>>> *(node->children) is exactly equivalent to (node->children)[0]
                            >>>>>which is the first element of that array. This element is obviously a
                            >>>>>pointer to struct.
                            >>>>> The space you allocate is not sufficient to hold such a struct.
                            >>>>>The struct consists of 27 struct pointers plus a void pointer plus any
                            >>>>>padding. You allocate only enough space for the 27 struct pointers.
                            >>>>> At this point you have committed the unpardonable sin of lying to
                            >>>>>the compiler. You have told it that node->children[0] will point to
                            >>>>>a struct and it doesn't.
                            >>>>>
                            >>>>>On top of all that, you don't need this code. The struct already
                            >>>>>contains an array of 27 pointers so you don't need another set.
                            >>>>
                            >>>>Hm...... I am not that clear about what I learnt. A var[] and *var can
                            >>>>be used interchangeably , but what's the difference? Does the compiler
                            >>>>allocate space for var[] but not *var?
                            >>>
                            >>>
                            >>>NO NO NO NO. A var[] is an array. A *var is a pointer. While they
                            >>>share a certain amount of common syntax using subscript notation they
                            >>>are by no means interchangeable . Read the faq. Look in your text.
                            >>>Google through the archives for postings that talk about pointers and
                            >>>arrays, especially those by CBFalconer.
                            >>>
                            >>>And for heaven's sake, don't say this to your instructor. The only
                            >>>possible result is bad. Either he will downgrade you for not
                            >>>understandin g a basic aspect of the language or he will agree with you
                            >>>and you will know he is incompetent and you have wasted a semester.[/color]
                            >>
                            >>OK, yes, my book says they have "strong relationship". I guess I should
                            >>study harder...
                            >>
                            >>[color=darkred]
                            >>>>Well actually if I don't free() the memory I allocated, will the memory
                            >>>>be free after the program quits?
                            >>>
                            >>>
                            >>>And you believe this is an excuse to write sloppy code?[/color]
                            >>
                            >>So is it required to free() the memory I allocated. I didn't do that
                            >>before unless required.[/color]
                            >
                            >
                            > The standard does not specify what the operating system will do when
                            > you program terminates. It is never wrong to clean up after your self
                            > and on a "not well designed system" it may in fact be necessary. I
                            > don't have a clue about whether your system will clean up your mess or
                            > not but in this newsgroup we don't depend on system specific behavior.[/color]

                            Wouldn't that be too hard to find out what is allocated and what is not?
                            That'll be a pain if that is a huge program. Is there any way to get a
                            list of memory allocated by the program and free them all when the
                            program quits?

                            Comment

                            • Barry Schwarz

                              #15
                              Re: Array of pointers in a struct

                              On Sat, 01 May 2004 21:36:06 -0500, fix <fix@here.com > wrote:
                              [color=blue]
                              >
                              >
                              >Barry Schwarz wrote:
                              >[color=green][color=darkred]
                              >>>OK, I didn't. But why does my program can still use malloca?[/color]
                              >>
                              >>
                              >> What is malloca?[/color]
                              >
                              >It's a typo.
                              >[color=green]
                              >> Your program uses malloc because you coded it to. Under C89, if you
                              >> call a function without a prototype, the compiler assumes that the
                              >> arguments are the correct type and the function returns an int. It
                              >> then generates the appropriate clues for the linker to include that
                              >> function in you program. Since the assumed return type is incorrect
                              >> for malloc, you have invoked undefined behavior.[/color]
                              >
                              >I meant, I don't include the header and can still call malloc, does the
                              >compiler know where to find the actual malloc implementation?[/color]

                              Go back and read the paragraph again. The compiler doesn't find the
                              actual code for malloc. The linker does.

                              And no, you cannot still call it. Any attempt to do so invokes
                              undefined behavior, regardless of whether or not the compiler
                              generates a diagnostic.

                              Do you have your warning level set to max? Many compilers will
                              generate a warning that there is no prototype in scope.

                              snip[color=blue][color=green]
                              >> The standard does not specify what the operating system will do when
                              >> you program terminates. It is never wrong to clean up after your self
                              >> and on a "not well designed system" it may in fact be necessary. I
                              >> don't have a clue about whether your system will clean up your mess or
                              >> not but in this newsgroup we don't depend on system specific behavior.[/color]
                              >
                              >Wouldn't that be too hard to find out what is allocated and what is not?
                              >That'll be a pain if that is a huge program. Is there any way to get a
                              >list of memory allocated by the program and free them all when the
                              >program quits?[/color]

                              It's only too hard if you code your program before you design it. A
                              well designed program will have one fclose for every successful fopen
                              and one free for every successful malloc, whether explicit or implied.
                              This is one of the reasons there is more to programming than merely
                              learning the language. (Just as an aside, it is legal to free the
                              NULL pointer returned by an unsuccessful malloc but it is not legal to
                              fclose the NULL pointer returned by an unsuccessful fopen.)

                              There is no standard language feature that will tell you all the areas
                              you have allocated. You have to keep track of them as you allocate
                              them. Since you normally assign the returned address to a pointer,
                              this is not as onerous as it sounds.


                              <<Remove the del for email>>

                              Comment

                              Working...