Thread: `struct declared inside parameter list' problem, seems ineluctable in such a case

  1. #1
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8

    Question `struct declared inside parameter list' problem, seems ineluctable in such a case

    Hi, I got this warning message when compiling a project under MinGW using gcc. Now, to simplify, I'll try to give an example:

    There are 3 files included in this problem, which belong to a large project:

    1) a.h
    2) b.h
    3) test.c

    a.h:

    Code:
    #ifndef A_H
    #define A_H
    
    #include "b.h"
    
    struct A
    {
    	int a;
    	int b;
    };
    
    void a_func(struct A *a, struct B *b);
    
    #endif
    As you can see, it declares a function named `a_func', which accepts a pointer to `struct A', and a pointer to `struct B' (so I included `b.h'). `a_func' might be defined in `a.c' and used elsewhere, which is not the problem.

    b.h:

    Code:
    #ifndef B_H
    #define B_H
    
    #include "a.h"
    
    struct B
    {
    	double i;
    	double j;
    	struct A *a;
    };
    
    #endif
    `struct B' contains a pointer to `struct A', so I included `a.h'.

    and test.c:

    Code:
    #include <stdio.h>
    #include "b.h"
    
    int main(void)
    {
    	struct B b;
    
    	b.i = 2.71;
    	b.j = 3.14;
    	printf("i is %f and j is %f\n", b.i, b.j);
    	
    	return 0;
    }
    Now compile test.c:

    Code:
    gcc -Wall -c test.c
    it says:

    Code:
    In file included from b.h:4,
                     from test.c:2:
    a.h:12: warning: "struct B" declared inside parameter list
    a.h:12: warning: its scope is only this definition or declaration, which is probably not what you want

    ***

    Now I understand that it is because after we included `b.h' in `test.c', `B_H' has been defined, and since `b.h' includes `a.h' while `a.h' includes `b.h' also (then `b.h' is actually not included in `a.h' because `B_H' has already been defined), the definition of `struct B' is not known by `a.h'.

    I also understand that, if i put `void a_func(struct A *a, struct B *b);' into `b.h', this problem is solved in this case, but this breaks the organization of this project since `a_func' is defined in `a.c', which is supposed to be with `a.h'.

    So if anyone has any idea to keep the declaration of `a_func' in `a.h' and meanwhile avoid the `struct declared inside parameter list' problem, I'll be very grateful.
    Last edited by babyifan; 09-29-2009 at 08:18 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You can do without the definition of struct B in a.h, so in fact you could remove the inclusion of b.h, replacing it with a forward declaration:
    Code:
    struct B;
    Likewise, the definition of struct B does not need the definition of struct A since struct B stores a pointer to struct A. As such, you can remove the inclusion of a.h from b.h, replacing it with a forward declaration of struct A.
    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

  3. #3
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8

    Unhappy

    Quote Originally Posted by laserlight View Post
    You can do without the definition of struct B in a.h, so in fact you could remove the inclusion of b.h, replacing it with a forward declaration:
    Code:
    struct B;
    Likewise, the definition of struct B does not need the definition of struct A since struct B stores a pointer to struct A. As such, you can remove the inclusion of a.h from b.h, replacing it with a forward declaration of struct A.

    Hi laserlight, I've tried your solution but it seems not to work. If we remove the inclusion of a.h from b.h, replacing it with a declaration of struct A, then how does GCC know the size of struct A when we malloc() space to `a' (the pointer to struct A)? The type of struct A is incomplete because after removing a.h, we don't know where to get definition of struct A, dereferencing pointer `a' will be impossible.

    Likewise, after removing b.h from a.h, we do have the declaration of struct B now, and we won't get `declared inside parameter list' warning, but we don't know the definition of struct B, so in function a_func, it is impossible to dereferencing pointer `b' to the right place.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by babyifan
    If we remove the inclusion of a.h from b.h, replacing it with a declaration of struct A, then how does GCC know the size of struct A when we malloc() space to `a' (the pointer to struct A)?
    You would include the relevant header files in the source files instead.
    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

  5. #5
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8
    Quote Originally Posted by laserlight View Post
    You would include the relevant header files in the source files instead.
    Sorry, I still can't get the point.

    I mean, in this minimized case, when a.h needs definition of some type in b.h, at the same time b.h needs definition of some type in a.h, but there were conditional directives guard in both headers:

    Code:
    #ifndef HEADER
    #define HEADER
    
    ...
    
    #endif
    and when i include one header in a C file, the side effect of the conditional directives guard appears: in my example, a.h won't include the content of b.h at all because B_H has already been defined, and the pitiful declarations in a.h that needs definitions in b.h will never get those definitions.

    I know I can solve this problem by moving the declaration of a_func to b.h, or moving the definition of struct B to a.h, or by using only one header for this problem, but it seems i'm a mysophobia in coding and src structure, so i do want to know if there exists other solutions.
    Last edited by babyifan; 09-29-2009 at 09:39 AM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by babyifan
    I mean, in this minimized case, when a.h needs definition of some type in b.h, at the same time b.h needs definition of some type in a.h
    No, a.h does not need the "definition of some type in b.h". a.h contains the definition of struct A, which does not involve struct B at all. It also contains a declaration of a_func, which does involve struct B, but only needs a declaration, not definition, of struct B. b.h does not need the "definition of some type in a.h", because struct B is defined in b.h, but its use of struct A involves a pointer to struct A, not a struct A object, as a member. Therefore, a declaration of struct A will suffice.

    Quote Originally Posted by babyifan
    and when i include one header in a C file, the side effect of the conditional directives guard appears: in my example, a.h won't include the content of b.h at all because B_H has already been defined, and the pitiful declarations in a.h that needs definitions in b.h will never get those definitions.
    Yes, but if you do it the way that I am recommending, then you will #include "b.h" in the source file where you define a_func (along with #include "a.h", presumably).
    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

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Hi laserlight, I've tried your solution but it seems not to work. If we remove the inclusion of a.h from b.h, replacing it with a declaration of struct A, then how does GCC know the size of struct A when we malloc() space to `a' (the pointer to struct A)? The type of struct A is incomplete because after removing a.h, we don't know where to get definition of struct A, dereferencing pointer `a' will be impossible.
    That's right. C compilers will accept forward references to structures when you only have pointers to the structure. So if you have a function prototype in a header file which involves pointers to a structure, you can get away with a forward declaration.

    When you go to implement this function in a source file, then you must #include the header file to get the full structure declaration. At this point, however, the prototype has already been accepted with the forward declaration, so the recursive inclusion problem doesn't matter.

    Try it. Use a forward declaration to define struct B in a.h. Then in a.c, #include "b.h". All should be well.
    dwk

    Seek and ye shall find. quaere et invenies.

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


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

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

  8. #8
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8

    Smile Thanks very much!

    Quote Originally Posted by laserlight View Post
    Yes, but if you do it the way that I am recommending, then you will #include "b.h" in the source file where you define a_func (along with #include "a.h", presumably).
    Quote Originally Posted by dwks View Post
    That's right. C compilers will accept forward references to structures when you only have pointers to the structure. So if you have a function prototype in a header file which involves pointers to a structure, you can get away with a forward declaration.

    When you go to implement this function in a source file, then you must #include the header file to get the full structure declaration. At this point, however, the prototype has already been accepted with the forward declaration, so the recursive inclusion problem doesn't matter.

    Try it. Use a forward declaration to define struct B in a.h. Then in a.c, #include "b.h". All should be well.
    I've tried the solution, and it works great. Thanks for helping me a lot!

  9. #9
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8
    Today I checked out Forward declaration - Wikipedia, the free encyclopedia , and I know that I've learned new things. laserlight, thanks for your patience and dwks, thanks for your clear explanation.
    Last edited by babyifan; 09-30-2009 at 08:14 AM.

  10. #10
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I've learned what "ineluctable" means. I shall use it to impress friends.

  11. #11
    Registered User babyifan's Avatar
    Join Date
    Sep 2009
    Location
    Shanghai
    Posts
    8

    Smile

    Quote Originally Posted by nonoob View Post
    I've learned what "ineluctable" means. I shall use it to impress friends.
    lol... I got this word from lingoes, it seems more difficult for me to write English than C, at least when I'm playing with C, I only need to look up the c library every once in a while, but when I'm writing English, I have to loop up the dictionary very frequently.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How can I make this code more elegant?
    By ejohns85 in forum C++ Programming
    Replies: 3
    Last Post: 04-02-2009, 08:55 AM
  2. help me debug this linked list !
    By Dark Angel in forum C Programming
    Replies: 6
    Last Post: 04-18-2008, 02:10 PM
  3. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  4. Linked List Help
    By CJ7Mudrover in forum C Programming
    Replies: 9
    Last Post: 03-10-2004, 10:33 PM
  5. singly linked list
    By clarinetster in forum C Programming
    Replies: 2
    Last Post: 08-26-2001, 10:21 PM

Tags for this Thread