Thread: dynamic array in STRUCT

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    114

    dynamic array in STRUCT

    Hi everyone,

    I am new to structs but I need them for some complex problem where the struct not simply contains arrays or pointers, but also arrays of pointers as shown below.

    What I can't figure out is how to dynamically allocate the array of pointers defined in the struct.

    Can anyone help me with this issue?
    thank you in advance. I can write my code without structs, but I rather use them to make it more readable and efficient.

    Thank you in advance

    Code:
    #define PROB_ENTRIES 10
    #define MAX_INPUT_ENTRIES 40
    
    typedef struct
    {
    
    	char *problem[];
    	float PROBVars[MAX_INPUT_ENTRIES]
    	
    } input;
    
    
    
    main()
    {
    ...
    
    char *problem[PROB_ENTRIES];
    	for(i=0; i<PROB_ENTRIES; i++)
    		problem[i] = (char*) malloc(32 * sizeof(char *));
    		
    ...
    }

  2. #2
    Registered User GL.Sam's Avatar
    Join Date
    Aug 2009
    Posts
    88
    float PROBVars[MAX_INPUT_ENTRIES]
    Add a semicolon.

    problem[i] = (char*) malloc(32 * sizeof(char *));
    Remove an asterisk.

    Better now?

    btw, don't use structs for such a simple case. I don't even understand why are you declaring *problem[] over again.
    Last edited by GL.Sam; 08-04-2009 at 04:19 AM.
    The only good is knowledge and the only evil is ignorance.
    ~Socrates

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by GL.Sam View Post
    Add a semicolon.


    Remove an asterisk.

    Better now?

    btw, don't use structs for such a simple case. I don't even understand why are you declaring *problem[] over again.
    Hi Sam, thanks for replying. I sent just a simple psuedo-code as example but I think I didn't explain myself correctly.

    The struct that I want to use is actually going to contain many elements (arrays of loats, arrays of pointers, strings, constants, etc.), but most of the arrays and arrays of pointers that I want to use inside the struct are supposed to be dynamic.

    What I cannot do correctly is dynamically allocate them and I don't know whether that step must be done inside the struct or in the main.c

    Thank you again

  4. #4
    Registered User GL.Sam's Avatar
    Join Date
    Aug 2009
    Posts
    88
    Don't ever try to allocate anything being in a struct block. And if you use array notation [] in there, it shouldn't be empty. It goes smt like following:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define PROB_ENTRIES 10
    
    
    struct input
    {
    
    	char *problem[PROB_ENTRIES];
    	
    };
    
    
    int main(void)
    {
            struct input huh;
    	int i;
    
    	for (i = 0; i < PROB_ENTRIES; i++)
    	{
    		huh.problem[i] = (char*) malloc(32 * sizeof(char));
            	strcpy(huh.problem[i], "What?");
    		printf("%s\n", huh.problem[i]);
    	}
    	
            return 0;
    
    }
    The only good is knowledge and the only evil is ignorance.
    ~Socrates

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Hi Sam, thank youi very much! This helps a lot

    All the best,
    cfd

  6. #6
    Registered User GL.Sam's Avatar
    Join Date
    Aug 2009
    Posts
    88
    No problem. Uh, and don't forget about the free()! I myself did.
    The only good is knowledge and the only evil is ignorance.
    ~Socrates

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by GL.Sam View Post
    No problem. Uh, and don't forget about the free()! I myself did.
    sure; about details I'll take care of them. I'm new to structs but still proficient in C

    thank you again

  8. #8
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Just 2 tips:
    * Drop the sizeof(char) since it's always 1.
    * Drop the cast on malloc()

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by zacs7 View Post
    Just 2 tips:
    * Drop the sizeof(char) since it's always 1.
    * Drop the cast on malloc()
    Hi Zacs, thanks for the hints

    Best,
    cfd

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Drop the sizeof(char) since it's always 1.
    Writing
    p = malloc ( sizeof(*p) * numRequired );
    will save you from doing something like

    int *p = malloc( 10 );
    in the belief that you've allocated 10 int's.

    Better still, because the sizeof uses the pointer variable itself for working out the size, you don't have to look back to make sure that the declaration type, and the type in the sizeof agree with one another. Change one, and the other is instantly correct!

    Choose one idiom, that always works.

    Optional programming, like
    - leaving braces off single-statements inside a control (for, if etc)
    - sizeof(char) being 1 for malloc
    - optional ( ) in complex arithmetic or boolean expressions
    will, sooner or later, mutate from"simple" code into something not so simple, and the optional becomes necessary. It might be months before the bug is noticed, and weeks more before it's finally tracked down and fixed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by Salem View Post
    > Drop the sizeof(char) since it's always 1.
    Writing
    p = malloc ( sizeof(*p) * numRequired );
    will save you from doing something like

    int *p = malloc( 10 );
    in the belief that you've allocated 10 int's.

    Better still, because the sizeof uses the pointer variable itself for working out the size, you don't have to look back to make sure that the declaration type, and the type in the sizeof agree with one another. Change one, and the other is instantly correct!

    Choose one idiom, that always works.

    Optional programming, like
    - leaving braces off single-statements inside a control (for, if etc)
    - sizeof(char) being 1 for malloc
    - optional ( ) in complex arithmetic or boolean expressions
    will, sooner or later, mutate from"simple" code into something not so simple, and the optional becomes necessary. It might be months before the bug is noticed, and weeks more before it's finally tracked down and fixed.
    Hi Salem,

    great hints; thanks so much

    Best regards,
    cfd

  12. #12
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by GL.Sam View Post
    Don't ever try to allocate anything being in a struct block. And if you use array notation [] in there, it shouldn't be empty. It goes smt like following:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define PROB_ENTRIES 10
    
    
    struct input
    {
    
    	char *problem[PROB_ENTRIES];
    	
    };
    
    
    int main(void)
    {
            struct input huh;
    	int i;
    
    	for (i = 0; i < PROB_ENTRIES; i++)
    	{
    		huh.problem[i] = (char*) malloc(32 * sizeof(char));
            	strcpy(huh.problem[i], "What?");
    		printf("%s\n", huh.problem[i]);
    	}
    	
            return 0;
    
    }
    Hi again Sam,

    I wrote a *.h file that contains my struct, and the definition of the function that uses the struct elements, and the corresponding READ_INPUT.c file and main calling READ_INPUT()

    1) READ_INPUT.h:
    Code:
    //Struct for the Boundary condition codes and values:
    typedef struct struct_bc
    {
        unsigned int nbdy_nodes;	// Number of boundary nodes
        unsigned int *NODE;			// Node index number
        unsigned int *BDY_CODE;		// Array of the boundary codes
        float *BDY_VALUES;			// Array of boundary values: size [nbdy_nodes]x[nvariables]
    
    }bc ;	//bc as Boundary Conditions	
    
    void READ_BC(char *bdy_file, bc *BDYCS);
    2) READ_INPUT.c:
    Code:
    void READ_BC(char *bdy_file, bc *BDYCS)
    {
    	FILE *bdyf_ID;
    	char header[16];
    	
    	BDYCS.NODE = (unsigned int*) malloc(10 * sizeof(unsigned int *));
    
    	free(BDYCS.NODE);
    	
    return;
    }
    but I get the following error in compilation:

    Code:
    READ_INPUT.c: In function ‘READ_BC’:
    READ_INPUT.c:127: error: request for member ‘NODE’ in something not a structure or union
    READ_INPUT.c:151: error: request for member ‘NODE’ in something not a structure or union
    make: *** [main.o] Error 1
    what am I doing wrong in using the structure arrays to allocate?

    thanks a lot

  13. #13
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    Use:

    Code:
       BDYCS->NODE = (unsigned int*) malloc(10 * sizeof(unsigned int *));

  14. #14
    Registered User
    Join Date
    Mar 2009
    Posts
    114
    Quote Originally Posted by slingerland3g View Post
    Use:

    Code:
       BDYCS->NODE = (unsigned int*) malloc(10 * sizeof(unsigned int *));
    Thank you

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I suggest that you reserve the use of fully capitalised names to macro names. Use descriptive names instead of using comments. Together, and excluding the inclusion guards, I would suggest this for your header file:
    Code:
    typedef struct boundary_conditions
    {
        unsigned int num_nodes; // Number of boundary nodes
        unsigned int *node;     // Node index number
        unsigned int *code;     // Array of the boundary codes
        float *values;          // Array of boundary values: size [nbdy_nodes]x[nvariables]
    } boundary_conditions;
    
    void read_boundary_conditions(char *bdy_file, boundary_conditions *bdy_conds);
    Now, what slingerland3g suggested is correct. However, an even better version (using my suggested changes) would be:
    Code:
    bdy_conds->node = malloc(10 * sizeof(*bdy_conds->node));
    The reason is that if the type of the node member changes, this would be factored in automatically, instead of having to change from unsigned int* to the new type.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. array of struct pointers
    By simo_mon in forum C Programming
    Replies: 4
    Last Post: 05-11-2009, 08:34 PM
  2. populate an array struct
    By flipguy_ph in forum C Programming
    Replies: 10
    Last Post: 04-17-2009, 04:07 PM
  3. Assignment HELP!!
    By cprogrammer22 in forum C Programming
    Replies: 35
    Last Post: 01-24-2009, 02:24 PM
  4. Replies: 10
    Last Post: 05-18-2006, 11:23 PM
  5. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM

Tags for this Thread