Thread: Passing Structure Pointers to Functions

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    182

    Passing Structure Pointers to Functions

    OK, I am working on a relatively big program, one that scans for directories and prints them nicely to a file, depending on many options that the user types at the command line.

    So the first thing I do is parse the options to a structure that contains many bool variables. The structure looks like this:

    Code:
    typedef struct arguments{
    	bool help;
    	bool recurse;
    	bool complete;
    	bool output;
    	bool verbose;
    	bool each_folder;
    	unsigned int other;
    	char filepath_arg[MAX_DIR_LENGTH];
    } DIR_OPTIONS;
    That structure is in a header file. And the bool variables will turn on or off many if()'s on the program, which will implement the options. My problem is that my source code is divided in many modules, the main module which basically parses the arguments and starts the dir scanning engine, which is in module dir.c that calls another module fileinit.c which initializes the file (or files) that will be written. So somehow, I have to pass the arguments to the other functions.

    First thing I thought was making the structure global:
    Code:
    DIR_OPTIONS options={0,0,0,0,0,0} //init as false
    
    int main(int argc, char *argv[])
    {
         ......
    }
    And in the other modules:

    Code:
    extern DIR_OPTIONS options;
    My solution works, but I don't know... I have seen absolutely no program that does this. But I have seen many programs that use pointers to pass options.

    So, I tried something like this:

    Code:
    int main(int argc,char *argv[])
    {
    	DIR_OPTIONS *options;
    	options=(DIR_OPTIONS *)malloc(sizeof(DIR_OPTIONS)); //allocate memory for the function
    	dir(options);
    }
    
    void dir(DIR_OPTIONS *options)
    {
    	...
    }
    But it simply doesn't work. For some reason the compiler gives me errors if I try to do something like
    Code:
    *options={0,0,0,0,0,0};
    and... it simply doesn't work. The program stops and the file it is supposed to write has nothing in it.

    So my big question is: How can I create a structure in the main() function, and pass it to other functions as a pointer? I don't want the recursive dir() function taking up stack space because of declaring a DIR_OPTIONS struct in it, so I just want to pass dir() a pointer. And I just don't want to make it global-external.

    Thanks a lot!!!

    P.S: Is there a reason why (apparently) global variables are not preferred? Or are they completely fine?

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    {0,0,...}
    syntax can only be used to initialize a struct. Once created, you can't do it anymore.
    A pointer is simple a variable that holds an address, so passing a structure directly won't work, naturally. What you need to do is to take the address of it using & while passing it. Then it will work you'll see.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    coool... why didn't I think of it??? Just call the function like this

    Code:
    dir(&options);
    let me try that very very fast.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, that's the ticket.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    IT WORKS!!!!!1!11one

    So... in the main function I have to use options.etc when referring to a variable in the struct, and in the other function I have to use the -> thingy.

    but, lets say I initialize the structure pointer in the main function. I need to allocate memory with malloc (right, just like I did in the preceding code?) first, and then I need to initilize the options->etc variables one by one? Isn't there a
    Code:
    options={}
    shortcut?

    Let me code it better... will this work?
    Code:
    DIR_OPTIONS *options
    options=(DIR_OPTIONS *)malloc(sizeof(DIR_OPTIONS));
    options->var1 = 0
    options->var2 = 0
    etc. etc.
    Thanks a bunch.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You don't need to allocate memory with malloc. Since the struct will always exist in main, you can still pass it to other functions without it going out of scope. So in this case you're fine.
    But if you need malloc in the future, all you need to do (with the same effect as {0}) is:
    Code:
    memset(var, 0, sizeof(*var));
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    And var would be the whole structure... right? (In my case, options)... or would it be the individual variables inside the structure?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, it would "zero out" an entire struct, so the whole variable. But in your case, it's not necessary since you don't need malloc at all.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    Thanks a lot!

    So, I don't have to use malloc to create the first structure, but I need it if I want to create more and more structures on the run? And.. when I do that, I just initialize them by using memset, and I could access it later using pointers?

    Wow.. these pointers are powerful.

    Oh and I bet I can do this too:
    Code:
    int main(int argc, char *argv[])
    {
    	DIR_OPTIONS options={0,0,0,0,0,0}
    	DIR_OPTIONS *address=&options;
    	
    	//call the dir function
    	dir(address);
    	
    	//and to later access the variables I can use
    	address->variable
    	//or
    	options.variable
    }
    Am I right?

    Thanks a lot Elysia. You really do know everything!

  10. #10
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by samus250 View Post
    Thanks a lot!

    So, I don't have to use malloc to create the first structure, but I need it if I want to create more and more structures on the run? And.. when I do that, I just initialize them by using memset, and I could access it later using pointers?

    Wow.. these pointers are powerful.

    Oh and I bet I can do this too:
    Code:
    int main(int argc, char *argv[])
    {
    	DIR_OPTIONS options={0,0,0,0,0,0}
    	DIR_OPTIONS *address=&options;
    	
    	//call the dir function
    	dir(address);
    	
    	//and to later access the variables I can use
    	address->variable
    	//or
    	options.variable
    }
    Am I right?

    Thanks a lot Elysia. You really do know everything!
    Exactly.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by samus250 View Post
    Thanks a lot!

    So, I don't have to use malloc to create the first structure, but I need it if I want to create more and more structures on the run? And.. when I do that, I just initialize them by using memset, and I could access it later using pointers?

    Wow.. these pointers are powerful.

    Oh and I bet I can do this too:

    Am I right?

    Thanks a lot Elysia. You really do know everything!
    Yes, pointers are very powerful. They're a backbone of the language.
    And yes, you can do as you show, but there's little point of it right there.
    It's possible to do this, too:

    Code:
    int main(int argc, char *argv[])
    {
    	DIR_OPTIONS options={0,0,0,0,0,0}
    	dir(&options); /* Pass options directly without the need of a temp var */
    	(&options)->help;
    	void* pOptions = malloc(1 * sizeof(DIR_OPTIONS));
    	if (pOptions) ((DIR_OPTIONS*)pOptions)->bHelp;
    	free(pOptions);
    }
    Among much else.
    But beware that pointers can also be very dangerous. It's very easy to forget to free memory alloced using malloc. And it's also very easy to use previously freed memory, as well.
    So the general rule is to avoid pointers if you don't need them. Especially ones allocated dynamically through malloc.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    Cool thanks a lot. I'll keep playing with these pointers.

    Oh and one last question (I promise)!
    I've seen this:

    Code:
    int main(int argc, char *argv[])
    {
    	function(argv);
    }
    
    void function(char **argv)
    {
    	...
    }
    Apparently, in the function() function, argv is treated the same way as if it was on main(). But why does the function need to be prototyped with **argv? What is that double asterisk thing?

    Thanks again.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It's a pointer to a pointer, which is what argv is.
    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

  14. #14
    Registered User
    Join Date
    Jan 2008
    Posts
    182
    Oh ok I get it. A pointer that points to the argv pointer. Smooth

    Thanks.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    A pointer that points to the argv pointer.
    Not quite. The argv pointer in function is a copy of the argv pointer in main.
    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. Passing structure by reference or pointer?
    By 7force in forum C Programming
    Replies: 8
    Last Post: 12-13-2010, 06:49 PM
  2. Replies: 2
    Last Post: 07-03-2008, 11:31 AM
  3. passing pointers outside of functions
    By thomas41546 in forum C Programming
    Replies: 6
    Last Post: 01-26-2008, 06:00 PM
  4. passing a structure
    By ckeener in forum C++ Programming
    Replies: 2
    Last Post: 05-11-2005, 08:01 AM
  5. Replies: 1
    Last Post: 01-20-2002, 11:50 AM