Thread: struct/pointer problem?

  1. #1
    Registered User
    Join Date
    May 2003
    Posts
    17

    struct/pointer problem?

    Okay, I'm a tad bit confused of exactley whats going on here...

    Take a look at the code...

    Code:
    /* this is in mud.h */
    typedef struct  flag_data		FLAG_DATA;
    
    struct FLAG_DATA
    {
    	char *flag;
    };
    
    /* this is in mud.c */
    /* flag tables */
    const struct FLAG_DATA mob_flags[] =
    {
    	{"level"},{"invis"},{ "seeinvis"},{"sneak"},{"stealth"}, { NULL }
    };
    
    /* and this is in utils.c */
    /* toggle a flag in flag_list to turn on, off, or a number */
    bool toggle_flag( D_MOBILE *dMob, FLAG_DATA flag_list[], char *flag, char *arg)
    {
    	int i;
    	for(i=0;flag_list[i].flag!=NULL;i++){ /* line 143 */
    		if(compares(flag, flag_list[i].flag)){ /* line 144 */
    			if(compares(arg, "on")){  
    				dMob->flags[i]=TRUE;    /* turn it on */
    				return TRUE;
    			}
    			else if(compares(arg, "off")){
    				dMob->flags[i]=FALSE;   /* turn it off */
    				return TRUE;
    			}
    			else{
    				i=atoi(arg);
    				if(i>0){
    					dMob->flags[i]=i;   /* it was a number, apply it */
    					return TRUE;
    				}
    				log(LOG_E, "toggle_flag: bad flag or arg, flag: %s | arg: %s", flag, arg);
    				return FALSE;
    			}
    		}			
    	}
    	log(LOG_E, "toggle_flag: bad flag or arg, flag: %s | arg: %s", flag, arg);
    	return FALSE;
    }
    I get the following errors:
    utils.c: In function `toggle_flag':
    utils.c:143: arithmetic on pointer to an incomplete type
    utils.c:143: dereferencing pointer to incomplete type
    utils.c:144: arithmetic on pointer to an incomplete type
    utils.c:144: dereferencing pointer to incomplete type

    Theres also another function I get many of the same errors for, but its very similar to this function.

    So my question.... what the heck is going on here? I'm a little confused what I'm doing wrong, and why the above code is giving me errors... I thought a pointer was declared using '*' and I don't have an '*' anywhere in ther above code to signify use of a pointer.... so any help or insight on this would be greatly appreciated.

    Thanks.
    [ Jase]

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    typedef struct  flag_data		FLAG_DATA;
    
    struct FLAG_DATA
    {
    	char *flag;
    };
    
    const struct FLAG_DATA mob_flags[] =
    {
    	{"level"},{"invis"},{ "seeinvis"},{"sneak"},{"stealth"}, { NULL }
    };
    
    bool toggle_flag( D_MOBILE *dMob, FLAG_DATA flag_list[], char *flag, char *arg)
    {
    	int i;
    	for(i=0;flag_list[i].flag!=NULL;i++){ /* line 143 */
    		if(compares(flag, flag_list[i].flag)){ /* line 144 */
    You have an incomplete type struct flag_data which is aliased as FLAG_DATA. You also have a type struct FLAG_DATA that is not the same as struct flag_data or FLAG_DATA. The function toggle_flag declares flag_list as a pointer to FLAG_DATA, an incomplete type struct flag_data.

    Try one of the following.
    Code:
    struct FLAG_DATA
    {
    	char *flag;
    };
    
    const struct FLAG_DATA mob_flags[] =
    {
    	{"level"},{"invis"},{ "seeinvis"},{"sneak"},{"stealth"}, { NULL }
    };
    
    bool toggle_flag( D_MOBILE *dMob, struct FLAG_DATA flag_list[], char *flag, char *arg)
    {
    	int i;
    	for(i=0;flag_list[i].flag!=NULL;i++){ /* line 143 */
    		if(compares(flag, flag_list[i].flag)){ /* line 144 */
    Code:
    typedef struct  flag_data		FLAG_DATA;
    
    struct  flag_data
    {
    	char *flag;
    };
    
    const FLAG_DATA mob_flags[] =
    {
    	{"level"},{"invis"},{ "seeinvis"},{"sneak"},{"stealth"}, { NULL }
    };
    
    bool toggle_flag( D_MOBILE *dMob, FLAG_DATA flag_list[], char *flag, char *arg)
    {
    	int i;
    	for(i=0;flag_list[i].flag!=NULL;i++){ /* line 143 */
    		if(compares(flag, flag_list[i].flag)){ /* line 144 */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    typedef struct  flag_data		FLAG_DATA;
    
    struct FLAG_DATA
    This should be wrong. What this should translate to is:

    struct struct flag_data

    Because you've deviced "FLAG_DATA" as "struct flag_data". Personally, I don't see the point in using typedef when #define has the same effect.

    What code base is this from? You'll probably want to drop in on the Mud Connector.

    [edit]Curses. Foiled again![/edit]

    Quzah.
    Last edited by quzah; 05-31-2003 at 09:59 AM.
    Hope is the first step on the road to disappointment.

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    17

    Thanks

    Hey,

    Thanks. I examined the last example you gave me and examined my code and realized I just wasn't paying attention to what I was doing. See I have several structures that follow the same method and work fine... which is why I was so boggled.

    Thanks again, your a life save.
    [ Jase]

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Personally, I don't see the point in using typedef when #define has the same effect.
    It limits confusion, #define is used for named constants and typedef for type aliases. Using #define for type aliases is generally a bad idea since you may end up with something like this:
    Code:
    #include <stdio.h>
    
    #define FLAG_DATA struct flag_data *
    
    struct flag_data {
        int flag;
        int flag2;
    };
    
    int main(void)
    {
        FLAG_DATA f1 = NULL,
                  f2 = NULL;
    
        return 0;
    }
    Uh oh! f2 isn't a pointer (this fact is neatly hidden by the #define), so such an initialization would be problematic at best. Using typedef would alleviate the problem:
    Code:
    #include <stdio.h>
    
    typedef struct flag_data *FLAG_DATA;
    
    struct flag_data {
        int flag1;
        int flag2;
    };
    
    int main(void)
    {
        FLAG_DATA f1 = NULL,
                  f2 = NULL;
    
        return 0;
    }
    typdef works on both of the variables, they're pointers and the initialization occurs as expected. I try not to use the preprocessor for anything except named values because anything else just smells funny. Of course, that may just be the C++ talking.
    My best code is written with the delete key.

  6. #6
    Registered User
    Join Date
    May 2003
    Posts
    17

    hmm...

    Actually, it generated another problem... think you could provide some insight on this one?

    Code:
    toggle_flag(dMob, mob_flags, "invis", "on");
    The one and only error I get:
    passing arg 2 of `toggle_flag' discards qualifiers from pointer target type

    Now, call me an idiot, but I've never gotten that error before, and I have no clue what it means. Or how to fix it.
    [ Jase]

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Originally posted by Prelude
    Using #define for type aliases is generally a bad idea since you may end up with something like this:
    Code:
    #include <stdio.h>
    
    #define FLAG_DATA struct flag_data *
    
    struct flag_data {
        int flag;
        int flag2;
    };
    
    int main(void)
    {
        FLAG_DATA f1 = NULL,
                  f2 = NULL;
    
        return 0;
    }
    Well I've always thought defining a "pointer type" was counter intuitive myself anyway. If I want a pointer, I specify *, if I don't, I don't.

    ie:

    typedef type * foo;

    foo x;

    Unless you use Hungarian notation or something similar, you can't easily telll by just the name that said type is supposed to be a pointer. I've just never liked that style myself.

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    May 2003
    Posts
    17
    Originally posted by quzah
    What code base is this from? You'll probably want to drop in on the Mud Connector.
    I'm writing my codebase from scratch. And so far so good. I have sockets, saving, loading, flags working(i'm just making an easy to use 'toggle system' for flags), as well as a map, walking, hiding/sneaking as well as seeing invis, emotes and channels. It's just I program from personal experience and examining other ppl's source code. I've taken very few tutorials, and only one years worth of very, very, basic computer science back in highschool(few years ago).

    I tend to have problems when trying new ideas and encountering new error messages, because I've never taken a class or a tutorial that prepared me to encounter that kind of thing...

    Anyhow, I've been using typedef without any problems on my socket structure, mobile structure, as well as command emotes and channels structure. and they all work well. Ran into a little problem with flag editting because I'm using the structures a tad bit different.

    [edit]
    Only thing I'm really worried about is memory leaks and using up too much or excess space in memory. Like I said, I program from personal experience and examing other ppl's source code. So what I see used I examine and test for hours until I figure out how it works, such as pointers and memory allocation. My mud is chock full of pointers here, and there. And I'm using the same methods of SMAUG and RESORTMUD from back 4 years ago. so I'm assuming I won't have too much of a problem with memory leaks other than forgetting to free allocated memory... but I'm still a little worried that with all my ponters goin round and round I might lose one here and there. But I guess I can only wait and see.
    [/edit]
    Last edited by Jase; 05-31-2003 at 10:25 AM.
    [ Jase]

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826

    Re: hmm...

    Originally posted by Jase
    Actually, it generated another problem... think you could provide some insight on this one?

    Code:
    toggle_flag(dMob, mob_flags, "invis", "on");
    The one and only error I get:
    passing arg 2 of `toggle_flag' discards qualifiers from pointer target type

    Now, call me an idiot, but I've never gotten that error before, and I have no clue what it means. Or how to fix it.
    Code:
    const struct FLAG_DATA mob_flags[] =
    See your problem now? In one case it's constant, in another, it isn't.

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    May 2003
    Posts
    17
    Ahh, gotcha. Thanks, about to fix it in my source here in a few seconds. Btw, I editted my above post. Added to it.
    [ Jase]

  11. #11
    Registered User
    Join Date
    May 2003
    Posts
    17
    by the way, what would it matter if I used 'const' 'static' or neither one in the declaration of the structure? I understand that const and(i think) static keep the data from being changed.. but If I don't have any functions that would change the data anyhow, whats the point of making it constant? is it because without const the structure is prone to a memory leak?

    Thanks again. I appreciate all the help you guys have given me.
    [ Jase]

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    If the function definition lets you throw away the const-ness, then it 'allows' you to write to what you have declared as being read-only.
    Code:
    #include<stdio.h>
    
    struct FLAG_DATA
    {
       char *flag;
    };
    
    const struct FLAG_DATA mob_flags[] =
    {
       {"level"},{"invis"},{"seeinvis"},{"sneak"},{"stealth"},{NULL}
    };
    
    const struct FLAG_DATA A = {"Uh-oh"};
    
    void foo(const struct FLAG_DATA *flag_list)
    {
       while ( flag_list->flag )
       {
          puts(flag_list++->flag); /* now that's ugly */
       }
    }
    
    void bar(/* const */ struct FLAG_DATA *flag_list)
    {
       while ( flag_list->flag )
       {
          *flag_list++ = A; /* you shouldn't be able to do this */
       }
    }
    
    int main(void)
    {
       foo(mob_flags);
       bar(mob_flags); /*lint !e605 ; Increase in pointer capability (arg. no. 1) */
       foo(mob_flags);
       return 0;
    }
    
    /* my output
    level
    invis
    seeinvis
    sneak
    stealth
    Uh-oh
    Uh-oh
    Uh-oh
    Uh-oh
    Uh-oh
    */
    Adding the const qualifier to the function bar would cause a compile error ("Cannot modify a const object in function bar"). Without it, you may only get a warning ("Suspicious pointer conversion in function main").
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    Registered User
    Join Date
    May 2003
    Posts
    17
    Originally posted by Salem
    > what would it matter if I used 'const' 'static' or neither one in the declaration of the structure?
    static is a storage qualifier - it changes where an object is stored in memory.
    Code:
    void foo ( void ) {
        int table[] = { 1, 2, 3 };
    }
    void bar ( void ) {
        static int table[] = { 1, 2, 3 };
    }
    In foo, the array is created at run-time on the stack, every time the function is called.
    In bar, the array is created in 'initialised data' by the compiler, and written just once when the program is loaded.
    The upside is, its quicker for large arrays
    The downside (sometimes) is that it remembers changes you make from one call to the next.
    So every time foo is called it creates the array and adds it to the stack? which would mean everytime I call foo it uses up more and more memory? Or after the function returns does it remove it from the stack? and if I were to use static, it would re-use the memory that has already been used?

    See, I use a common used variable, buf[MAX_BUFFER]; for storing stuff I might want to keep until the end of a function, or add to. I declare it as: char buf[MAX_BUFFER];

    so say I have 100 different functions that use buf[MAX_BUFFER]... each time one of those are called it would use up more memory to store the array into? And if I were to use static char buf[MAX_BUFFER] it would re-use the memory that has already been used to store the array the first time it was called?
    [ Jase]

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Static doesn't keep it from being changed. Static makes it (on local variables) persist between function calls. On global variables, and functions, it limits the scope of the variable to the function it is called in.
    Code:
    static void foo( void )
    {
        printf("This can only be called from whatever file it is in.\n");
    }
    const prevents a variable from being changed. It's usually a good idea to declare anything (in the function prototype) that won't be changed as 'const'. This is mainly something you'll use in C++ for accessor functions, but it's still good practice.

    Quzah.
    Hope is the first step on the road to disappointment.

  15. #15
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    So every time foo is called it creates the array and adds it to the stack? which would mean everytime I call foo it uses up more and more memory? Or after the function returns does it remove it from the stack? and if I were to use static, it would re-use the memory that has already been used?
    Every non-static, non-global variable and function call goes on the stack. When the end of scope is reached, the variable or function call is removed from the stack.

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM