'typedef struct' and 'struct'

This is a discussion on 'typedef struct' and 'struct' within the C Programming forums, part of the General Programming Boards category; Hi. I'm having a bit of a problem and it may be a problem of understanding the concept of typedef ...

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    9

    'typedef struct' and 'struct'

    Hi. I'm having a bit of a problem and it may be a problem of understanding the concept of typedef struct and struct. It's about how to access them I believe.

    At first, I have these part-structs in my header:

    Code:
    struct Statefile{
    
    
    	unsigned short int 		tank1Alive;
    	unsigned short int 		tank2Alive;
    	unsigned short int 		mapDimensionsX;
    	unsigned short int 		mapDimensionsY;
    	unsigned short int 		initialFuel;
    	unsigned short int 		initialAmmo;
    }State;
    struct Statefile *s =&State; 
    
    	struct Turnfile{
    		char* firing;
    		unsigned short int  targetX;
    		unsigned short int  targetY;
    		unsigned short int  movement;
    	} Turn;
    	struct Turnfile *p = &Turn;
    The Statefile struct gets its parameter filled by reading from the textfile. The Turnfile struct is to write a file called (whatever).tmp (for the time being then be converted to .turn <<nvm>>).

    Then I have defied this struct:

    Code:
    typedef struct {
    unsigned short int xMap;
    unsigned short int yMap;
    unsigned short int alive1;
    unsigned short int alive2;
    unsigned short int Ammo;
    unsigned short int Fuel;
    char* Move;
    } tankState;

    To get them filled, I used this function in my main:
    Code:
    tankState get_State( unsigned short int xMap, unsigned short int yMap, unsigned short int Ammo, unsigned short int Fuel, char* Move, unsigned short int alive1, unsigned short int alive2)
    
    
    {
    	tankState t;
    	t.alive1 = alive1;
    	t.alive2 = alive2;
    	t.Ammo = Ammo;
    	t.Fuel = Fuel;
    	t.xMap = xMap;
    	t.yMap = yMap;
    	t.Move = Move;
    	return t;
    }
    Then I want my program to a use this function to do stuff ( I'm designing an Algorithm AI ).

    Code:
    tankState tank_move( tankState a, tankState b, tankState c, tankState d, tankState g, tankState i, tankState m)
    {
    	tankState t;
    	
    	t.alive1 = b.alive1;
    	t.alive2 = c.alive2;
    	t.Fuel = a.Fuel;
    	t.xMap = g.xMap;
    	t.yMap = i.yMap;
    	t.Move = m.Move;
            t.Ammo = d.Ammo;
    
    	       {
                  my commands
    		}
    	
    	return t;
    }
    So, the function usage in my main looks like ( I used a combination (the arguments of tank_move) of what I thought may work to show you):

    Code:
    get_State(s->mapDimensionsX, s->mapDimensionsY, s->initialAmmo, s->initialFuel, p->movement, s->tank1Alive, s->tank2Alive);
    
    if(s->initialFuel >0 && s->tank1Alive==1 && s->tank2Alive==1 && (s->tank1Fired==0 && s->tank2Fired==1)
    {
    tank_move(tankState.xMap, tankState.yMap, tankState.Fuel, tankState.Move, tankState.xPosition1, tankState.yPosition1, s->tank2PositionX, s->tank2PositionY, s->tank1Alive, s->tank2Alive);
    }

    When I insert "tankState.(whatever)", it says "illegal use of tankState"
    And when I use "s->(whatever)", it says "cannot convert from tankState to unsigned short".

    So, my question is: How can I fix my problem ?

    Thank you for reading =)

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    tankState is a type because of the "typedef" before the struct. You haven't created an actual instance.
    Also, more appropriate names than a, b, c, d is recommended.
    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
    Oct 2010
    Posts
    9
    Quote Originally Posted by Elysia View Post
    tankState is a type because of the "typedef" before the struct. You haven't created an actual instance.
    Also, more appropriate names than a, b, c, d is recommended.
    Thanks for the tips =D


    I'm novice when at C cuz I'm still doing first semester in Mechatronics. So, just in case I do stupid mistakes, I'm not a real programmer yet ^__^"


    So, that means tankState.(whatever) is invalid because tankState is a type I defined ( I know this, but I dunno why I tried to attempt using it this way xD ).

    For the s->(whatever) trial, I receive this error message:
    'tank_move' : cannot convert parameter 1 from 'unsigned short' to 'tankState'

    Then...I tried to cast s->(whatever) into tankState, but didn't seem to work.
    Error message:
    'type cast' : cannot convert from 'unsigned short' to 'tankState'

    But can I know how to fix it?

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Ah, I missed that.
    But that one is also easy to answer. TankState is a type that is totally unrelated to a unsigned short. There is simply no context in which such a conversion can take place. The operation is undefined.
    So, in order to make it work, you have to define the operation. In C, this isn't possible in that sense. What you instead have to do is break it down into defined conversions.

    It is akin to converting an apple into a banana. How is that conversion going to be done? You are going to have to be explicit on how to do it. You could, say, you paint it yellow and trim it so it looks like a banana. Then you've defined the operation in smaller, defined, operations.
    I hope you get the point.
    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
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,175
    You're not passing tankState arguments into tank_move(); you're passing the members of the structs instead, which are are unsigned ints.

    I'm not sure what Elysia is trying to make you do with converting tankStates to unsigned ints or whatever, but it seems very strange. You're goal is not to convert unsigned ints to tankStates. You just need to update the members of your tankState instances with unsigned ints.
    If you understand what you're doing, you're not learning anything.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Quote Originally Posted by itsme86 View Post
    I'm not sure what Elysia is trying to make you do with converting tankStates to unsigned ints or whatever, but it seems very strange. You're goal is not to convert unsigned ints to tankStates. You just need to update the members of your tankState instances with unsigned ints.
    That was my point. That is what the OP is trying to do, and I am simply saying that such a conversion will never make any sense.
    You have to explicitly tell the compiler how it makes sense by doing the conversion manually.
    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
    Oct 2010
    Posts
    9
    itsme86: I'm trying to update the members of tankState by using the function "get_State".
    Then, how can I access the members of tankState, so I could use my "tank_move" function?
    As Elysia said, tankState is a type that I defined

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Both your GetTank and MoveTank functions look correct.
    It would be easier if you actually provided the smallest possible compilable example of your code that you are having trouble with.
    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
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,175
    Just get rid of the typedef and tankState becomes an instance of the struct instead of a type referring to the struct definition.

    Consider the following:
    Code:
    struct struct1
    {
      int a;
      int b;
    };
    typedef struct struct1 S;
    It's equivalent to doing this:
    Code:
    typedef struct struct1
    {
      int a;
      int b;
    } S;
    The latter is just a shorthand way of doing the former. All the typedef allows you to do is refer to the struct in a more terse manner. With the above typedef you could instantiate the struct this way:
    Code:
    struct struct1 myStructInstance;
    ... or this way:
    Code:
    S myStructInstance;
    Hopefully that makes things a little clearer.
    If you understand what you're doing, you're not learning anything.

  10. #10
    Registered User
    Join Date
    Oct 2010
    Posts
    9
    Actually, there's a trick in here, but I thought I might tackle it later.. since I'm going to provide what my code would look like, I'll just put it along =)

    The trick is, the typdef struct is having unsigned short int for "alive and fired"... but my .STATE file ( the file I read to feed my Statefile struct ) is having "alive and fired" as "true" and "false". Why am I using it this way? it's just a requirement ~.~.


    my header:

    Code:
    typedef struct {
    unsigned short int xMap;
    unsigned short int yMap;
    unsigned short int xPosition1; /*X position of player1 tank*/
    unsigned short int yPosition1; /*Y position of player1 tank*/
    unsigned short int alive1; /*1 if my tank is still alive, 0 if I've
    been destroyed*/
    unsigned short int fired1; /*1 if my tank has fired, 0 otherwise*/
    unsigned short int xPosition2; /*X position of player2 tank*/
    unsigned short int yPosition2; /*Y position of player2 tank*/
    unsigned short int alive2; /*1 if their tank is still alive, 0 if I've
    been destroyed*/
    unsigned short int fired2; /*1 if their tank has fired, 0 otherwise*/
    unsigned short int Ammo;
    unsigned short int Fuel;
    char* Move;
    unsigned short int shellVelocity;
    
    } tankState;
    
    
    //Defining the members of struct for the State file
    struct Statefile{
    
    	char*	tank1Fired; 
    	char*	tank2Fired; 
    	char*	tank1Alive;
    	char*	tank2Alive;
    	unsigned short int 		mapDimensionsX;
    	unsigned short int 		mapDimensionsY;
    	unsigned short int 		tank1PositionX;
    	unsigned short int 		tank1PositionY;
    	unsigned short int 		tank2PositionX; 
    	unsigned short int 		tank2PositionY; 
    	unsigned short int 		shellVelocity; 
    	unsigned short int 		initialAmmo;
    	unsigned short int 		initialFuel;
    }State;
    struct Statefile *s =&State; // assigning a pointer to the struct
    
    
    //Defining the members of struct for the Turn file
    	struct Turnfile{
    		char* firing;
    		unsigned short int  targetX;
    		unsigned short int  targetY;
    		char* movement;
    	} Turn;
    	struct Turnfile *p = &Turn; // assigning a pointer to the struct
    
    char* extractFileName(const char filePath[])
    
    {
    
    	char fileName[200];
    	size_t fileNameLength;
    
    	int i, j;
    	for (i = strlen(filePath); filePath[i] != '\\'; i--) 
    		if (i == 0) return 0;
    	i++;
    	fileNameLength = strlen(filePath);
    	for (j=0 ; filePath[i] != '.' && j < fileNameLength; j++, i++) 
    		fileName[j] = filePath[i]; 
    	fileName[j] = '\0';
    	return fileName;
    	//note, this function FAILS if a SPACE was present in the filePath
    }
    
    tankState get_State( unsigned short int xMap, unsigned short int yMap, unsigned short int shellVelocity, unsigned short int Ammo,
    					unsigned short int Fuel, char* Move,unsigned short int xPosition1, unsigned short int yPosition1,
    					unsigned short int xPosition2, unsigned short int yPosition2, unsigned short int fired1,
    					unsigned short int fired2, unsigned short int alive1, unsigned short int alive2)
    {
    	tankState t;
    	t.xPosition1 = xPosition1 ;
    	t.yPosition1 = yPosition1;
    	t.xPosition2 = xPosition2 ;
    	t.yPosition2 = yPosition2;
    	t.alive1 = alive1;
    	t.fired1 = fired1;
    	t.alive2 = alive2;
    	t.fired2 = fired2;
    	t.Ammo = Ammo;
    	t.Fuel = Fuel;
    	t.xMap = xMap;
    	t.yMap = yMap;
    	t.Move = Move;
    	return t;
    }
    
    tankState tank_move(tankState xpos1, tankState ypos1,tankState xpos2,tankState ypos2,tankState alive1,
    					tankState alive2,tankState fired1, tankState fired2,tankState Fuel,tankState xMap,
    					tankState yMap,tankState Move)
    {
    	tankState t;
    	t.xPosition1 = xpos1.xPosition1 ;
    	t.yPosition1 = ypos2.yPosition1;
    	t.xPosition2 = xpos2.xPosition2 ;
    	t.yPosition2 = ypos2.yPosition2;
    	t.alive1 = alive1.alive1;
    	t.fired1 = fired1.fired1;
    	t.alive2 = alive2.alive2;
    	t.fired2 = fired2.fired2;
    	t.Fuel = Fuel.Fuel;
    	t.xMap = xMap.xMap;
    	t.yMap = yMap.yMap;
    	t.Move = Move.Move;
    
    	if(Fuel.Fuel >0 && alive1.alive1==1 && alive2.alive2==1 && fired1.fired1==0 && fired2.fired2==1)
    	{
    		for (; xpos1.xPosition1 < xMap.xMap &&  ypos1.yPosition1 < yMap.yMap ;){
    		if ( xpos1.xPosition1 - xpos2.xPosition2 <-11 )
    		{ xpos1.xPosition1 = xpos1.xPosition1 +1;
    		Move.Move = "right";}
    		else if ( xpos1.xPosition1 - xpos2.xPosition2 >11 )
    		{ xpos1.xPosition1 = xpos1.xPosition1 -1;
    		Move.Move = "left";}
    		else if ( -11 < (xpos1.xPosition1 - xpos2.xPosition2) <11 && xpos1.xPosition1 > xpos2.xPosition2)
    		{xpos1.xPosition1 = xpos1.xPosition1 +1;
    		Move.Move = "right";} 
    		else if ( -11 < (xpos1.xPosition1 - xpos2.xPosition2) <11 && xpos1.xPosition1 < xpos2.xPosition2)
    		{ xpos1.xPosition1 = xpos1.xPosition1 -1;
    		Move.Move = "left";}
    		else if ( ypos1.yPosition1 - ypos2.yPosition2 <-16 )
    		{ypos1.yPosition1 = ypos1.yPosition1 +1;
    		Move.Move ="up";} 
    		else if ( ypos1.yPosition1 - ypos2.yPosition2 >16 )
    		{ ypos1.yPosition1 = ypos1.yPosition1 -1;
    		Move.Move = "down";}
    		else if (-16< (ypos1.yPosition1 - ypos2.yPosition2) < 16 && ypos1.yPosition1 > ypos2.yPosition2)
    		{ypos1.yPosition1 = ypos1.yPosition1 +1;
    		Move.Move = "up";}
    		else if(-16< (ypos1.yPosition1 - ypos2.yPosition2) < 16 && ypos1.yPosition1 < ypos2.yPosition2)
    		{ypos1.yPosition1 = ypos1.yPosition1 -1;
    		Move.Move = "down";}
    		Fuel.Fuel = Fuel.Fuel -1;
    			  
    		break;
    		}
    	}
    	return t;
    }

    my source:


    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <cstring>
    #include <windows.h>
    #include <math.h>
    
    void main(int argc, char* argv[])
    {
    int i;
    	for (i=0 ; i<argc; i++)
    	{
           //printf("player %d \nName of file: %s\n", i, argv[i]); // printing my player number
    	}
    
    		 extractFileName(argv[0]); // extracting the name of file
    
    //Creating the Read/Write Files.
    FILE *outfile, *infile;
    char buffer1 [30]; // for STATE file
    char buffer2 [30]; // for TEMP file
    char buffer3 [30]; // for TURN file
    int  t=1;
    
    //Using the format given to name the state file
    sprintf(buffer1, "p%dt%03d.state", i, t);
    infile = fopen (buffer1,"r");
    
    fscanf(infile, "%*s %d %d\n", &, &tankState.yMap.yMap);
    fscanf(infile, "%*s %d\n", &s->shellVelocity);
    fscanf(infile, "%*s %d\n", &s->initialAmmo);
    fscanf(infile, "%*s %d\n", &s->initialFuel);
    fscanf(infile, "%*s %d %d\n", &s->tank1PositionX, &s->tank1PositionY);
    fscanf(infile, "%*s %d %d\n", &s->tank2PositionX, &s->tank2PositionY);
    fscanf(infile, "%*s %s\n", &s->tank1Fired);
    fscanf(infile, "%*s %s\n", &s->tank2Fired);
    fscanf(infile, "%*s %s\n", &s->tank1Alive);
    fscanf(infile, "%*s %s\n", &s->tank2Alive);
    
    sprintf(buffer2, "p%dt%03d.tmp", i, t);
    outfile = fopen (buffer2,"w");
    
    fprintf(outfile, "firing \t%s\n", p->firing);
    fprintf(outfile, "target \t%d %d\n", p->targetX, p->targetY);
    fprintf(outfile, "movment \t%s\n", p->movement);
    fclose(outfile);
    
    rename ("p%dt%03d.tmp", "p%dt%03d.turn"); // renaming the file to .turn
    sprintf(buffer3, "p%dt%03d.turn", i, t);
    
    get_State(s->mapDimensionsX, s->mapDimensionsY,s->shellVelocity, s->initialAmmo, 
    s->initialFuel, p->movement,s->tank1PositionX, s->tank1PositionY, s->tank2PositionX, s->tank2PositionY,
     (unsigned short)s->tank1Fired, (unsigned short)s->tank2Fired, (unsigned short)s->tank1Alive, (unsigned short)s->tank2Alive);
    
    
    
    tank_move();
    }
    Last edited by nawaf; 10-23-2010 at 07:23 PM.

  11. #11
    Registered User
    Join Date
    Oct 2010
    Posts
    9
    Quote Originally Posted by itsme86 View Post
    Just get rid of the typedef and tankState becomes an instance of the struct instead of a type referring to the struct definition.

    Consider the following:
    Code:
    struct struct1
    {
      int a;
      int b;
    };
    typedef struct struct1 S;
    It's equivalent to doing this:
    Code:
    typedef struct struct1
    {
      int a;
      int b;
    } S;
    The latter is just a shorthand way of doing the former. All the typedef allows you to do is refer to the struct in a more terse manner. With the above typedef you could instantiate the struct this way:
    Code:
    struct struct1 myStructInstance;
    ... or this way:
    Code:
    S myStructInstance;
    Hopefully that makes things a little clearer.

    Thanks so much for the explanation, but I'm "supposed" to use that typedef struct and get the aid of other structs if desired (as part of my project).

  12. #12
    Registered User
    Join Date
    Oct 2010
    Posts
    9
    Thanks for the support guys !!
    I was able to fix it =D

    Thanks again

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. casting struct to struct
    By klmdb in forum C Programming
    Replies: 6
    Last Post: 08-14-2010, 03:29 PM
  2. help assignment due tomorrow
    By wildiv in forum C Programming
    Replies: 6
    Last Post: 01-27-2010, 08:38 PM
  3. Converting from C to C++
    By Taka in forum C++ Programming
    Replies: 5
    Last Post: 04-08-2009, 03:16 AM
  4. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 04:25 AM
  5. Replies: 10
    Last Post: 05-19-2006, 12:23 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21