LinuxQuestions.org
View the Most Wanted LQ Wiki articles.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 02-05-2009, 06:52 PM   #1
CoderMan
Member
 
Registered: Jan 2009
Location: Gemini Capsule 25164
Distribution: Gentoo
Posts: 375
Blog Entries: 24

Rep: Reputation: 43
Unhappy ARGGGH! Passing array of structs to function in C.


(whimper, whimper) Could someone help me with a problem related to passing an array of structs to a function? I wanted to use an array of structs because it sounded like it would be so convenient...

Here's a snippet from the header file where struct type is declared:

menuitem.h
Code:
typedef struct {
  char command[256];
  char key_assignment;
  char label[256];
} MenuItem;
I create this array of them and call it MENUITEM_ARRAY, and put a bunch of data into the elements. Then I try to pass it to a function like so:

Code:
draw_menu_screen(&MENUCONFIG, MENUITEM_ARRAY, TOTAL_MENUITEMS);
But when I try to compile with gcc I get this error message:

Code:
/minmenu.c:61: error: incompatible type for argument 2 of ‘draw_menu_screen’
I tried replacing it with this:

Code:
draw_menu_screen(&MENUCONFIG, &MENUITEM_ARRAY, TOTAL_MENUITEMS);
It compiles, but then then inside the function the data is all garbled or missing when I pull it out of the array elements. I used GDB to debug and know for sure that all the data in MENUITEM_ARRAY is intact and accessible up to the point where it is called by draw_menu_screen.

Here is the prototype for draw_menu_screen:

menu_screen.h

Code:
void draw_menu_screen(MenuConfig *, MenuItem *, int);
And here is (some of) the function itself:

menu_screen.c
Code:
void draw_menu_screen(MenuConfig * menuconfig, MenuItem * menuitems, int total_menuitems) {
   // do stuff here with data in MenuItem elements inside menuitems array
}
 
Old 02-05-2009, 07:01 PM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,395
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
What you've posted looks fine to me. Where is the code that creates the array of structs?
--- rod.
 
Old 02-05-2009, 07:28 PM   #3
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
To elaborate what I think NBomber is asking:

1. If you allocate the struct *outside* of draw_menu_screen(), it should work fine.

2. If you allocate the struct *inside* of draw_menu_screen() (and then pass it back to the caller, you need to:

a) declare your struct to be a pointer
b) make the argument a pointer to a pointer (**pp)

'Hope that helps .. PSM

PS:
Anonymous parameters can really be Bad News (from a maintenance/code readability standpoint). I'd strongly encourage you to make the prototype (which now has anonymous parameters) look exactly the same as your actual function (which instead uses named parameters). Trust me - you'll probably thank yourself the first time you change your argument list; and the poor guy who maintains the code will *definitely* thank you.

IMHO .. PSM
 
Old 02-05-2009, 07:36 PM   #4
CoderMan
Member
 
Registered: Jan 2009
Location: Gemini Capsule 25164
Distribution: Gentoo
Posts: 375
Blog Entries: 24

Original Poster
Rep: Reputation: 43
Quote:
Originally Posted by theNbomr View Post
What you've posted looks fine to me. Where is the code that creates the array of structs?
--- rod.
(Side note: All the following code is part of a GPLv3 project.)

The array is defined in the "process_cfg.c" source file outside of any function:

process_cfg.c
Code:
MenuItem * MENUITEM_ARRAY;
I "extern" it in the header file, so it will be accessible to all functions in the program:

process_cfg.h
Code:
extern MenuItem MENUITEM_ARRAY;
There is a function in "process_cfg.c" called "process_cfg_file" which allocates memory for the array and fills the array elements with data. (The function doesn't actually return the array of receive it as an argument). The function is rather long but here is the part where the memory is allocated:

Code:
MENUITEM_ARRAY = allocate_menuitem_array(menuitems_needed);
"allocate_menuitem_array" is a function from "menuitem.c":

menuitem.c
Code:
MenuItem * allocate_menuitem_array(int number_of_elements) {
  MenuItem * menuitem_array = malloc(number_of_elements*sizeof(MenuItem));
  if(menuitem_array == NULL) { return NULL; }
  return menuitem_array;
}
And here is where MENUITEM will receive more memory if needed:

process_cfg.h
Code:
    if(TOTAL_MENUITEMS == menuitems_needed) {
      menuitems_needed += 10;
      if(reallocate_menuitem_array(menuitems_needed, MENUITEM_ARRAY) == NULL) {
        strcpy(process_cfg_errstr, "I was unable to allocate sufficient memory to process the configuration file.\n");
        return 0;
      }
    }
And here is "reallocate_menuitem_array":

menuitem.c
Code:
MenuItem * reallocate_menuitem_array(int number_of_elements, MenuItem * menuitem_array) {
  MenuItem * new_menuitem_array = realloc(menuitem_array, number_of_elements*sizeof(MenuItem));
  if(new_menuitem_array == NULL) { return NULL; }
  return new_menuitem_array;
}
Code where the data itself is filled into the array elements is quite a bit longer, because it is being parsed from a config file.

Does that help?
 
Old 02-05-2009, 07:48 PM   #5
CoderMan
Member
 
Registered: Jan 2009
Location: Gemini Capsule 25164
Distribution: Gentoo
Posts: 375
Blog Entries: 24

Original Poster
Rep: Reputation: 43
Talking

Holy Byte-code Batman! I answered my question trying to answer yours! My "extern" statement was written wrong! It is supposed to be:

Code:
extern MenuItem * MENUITEM_ARRAY;
One stinkin' asterisk... Now the whole program works!

(CoderMan hands theNbomr a cigar.)
 
Old 02-05-2009, 10:44 PM   #6
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 114Reputation: 114
Quote:
Originally Posted by CoderMan View Post
Holy Byte-code Batman! I answered my question trying to answer yours! My "extern" statement was written wrong! It is supposed to be:

Code:
extern MenuItem * MENUITEM_ARRAY;
One stinkin' asterisk... Now the whole program works!

(CoderMan hands theNbomr a cigar.)
LOL. I spotted that. Good thing I read to the end of the thread first.

Happens that way a lot. You post a question, and find your own answer while trying to explain what is going on.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Passing Array Elements to functions melikai Programming 4 10-31-2006 10:27 PM
c: iterate an array of structs kpachopoulos Programming 2 08-15-2006 11:06 AM
Array structs - passed to function cdog Programming 4 02-02-2006 03:07 PM
confusing array of structs kpachopoulos Programming 1 11-23-2005 02:13 PM
A main can be changed by a function local without passing anything to the function? ananthbv Programming 10 05-04-2004 01:31 PM


All times are GMT -5. The time now is 08:22 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration