I've got some homework troubles with C struct… if anyone can be helpful. Because I don't get it.
The working code contains those bits (It's a game with a snake that has a head containing a direction):
game_t *game = …;
game->snake.head->direction = …;
snake_info(game->snake)
snake_destroy(&(game->snake));
The prototypes (I apparently cannot change):
void snake_info(snake_t const *snake);
void snake_destroy(snake_t *snake);
And the structure I'm trying to build.
typedef struct game {
snake_t snake; // to match call to snake_destroy and direction assignation
// or
snake_t *snake; // to match call to snake_info
} game_t;
But I cannot get both to work at the same time.
EDIT: the struct was called snake while it's actually game.
Do I miss something obvious or is there a problem with those prototypes (or calls)?
EDIT 2:
Compiler error with the first solution snake_t snake (in game):
snake.c: In function ‘game_print’:
snake.c:244:5: erreur: incompatible type for argument 1 of ‘snake_info’
gamecore.c:20:6: note: expected ‘const struct snake_t *’ but argument is of type ‘snake_t’
Compiler error with the second solution ̀ snake_t *snake`:
snake.c: In function ‘game_destroy’:
snake.c:205:5: attention : passing argument 1 of ‘snake_destroy’ from incompatible pointer type
gamecore.c:54:6: note: expected ‘struct snake_t *’ but argument is of type ‘struct snake_t **’
Your struct is incorrect. You have two members both with the same name 'snake'
Both must have unique names within the scope of the struct to permit legal code
The compiler error says it all, you have to define your struct using struct snake_t:
typedef struct game {
struct snake_t snake;
} game_t;
You have to use snake_t snake because of snake.head within the given code.
There is a bit of confusion with where pointers are used. With more practice using pointers will become more natural to you.
Also, use variable names that do not conflict with the names of structures.
Depending upon how much pointer usage you want in your code.
Minimal edits to existing code:
typedef struct game {
snake_t snake; // A snake_t instance is created with the game instance..
} game_t;
--
game_t *game = …;
game->snake.head->direction = …;
// snake_info requires a snake_t reference so pass the address of game->snake
//snake_info(game->snake);
snake_info(&(game->snake));
snake_destroy(&(game->snake));
Minimal pointers:
typedef struct game {
snake_t snake; // A snake_t instance is created with the game instance..
} game_t;
--
// Use a game_t variable instead of a pointer
//game_t *game = …;
game_t aGame = …; // renamed variable to avoid conflicts
// change the snake.head to snake->head since the game object uses a snake_t pointer
// game->snake.head->direction = …;
aGame.snake.head->direction = …;
// Pass the address of aGame.snake
snake_info(&(aGame.snake));
// this line is okay since you pass the address of game->snake.
snake_destroy(&(aGame.snake));
Making more use of pointers:
typedef struct game {
snake_t *snake; // A pointer to a snake_t instance.
} game_t;
--
// Create a game_t instance
game_t aGame = …;
// Create a snake_t instance
snake_t aSnake = ... ;
// Create a game_t pointer and assign it the address of aGame
game_t *aGamePtr = &aGame;
// Using aGamePtr, assign the snake variable in aGame the address of aSnake
aGamePtr->snake = &aSnake;
// Since the game_t object is a snake_t pointer,
// change the snake.head to snake->head
// game->snake.head->direction = …;
aGamePtr->snake->head->direction = …;
// this line is okay since aGamePtr->snake is a pointer.
snake_info(aGamePtr->snake);
// Since game object uses a snake_t pointer, pass aGamePtr->snake directly
// snake_destroy(&(game->snake));
snake_destroy(aGamePtr->snake);
Related
I am developing a TIN model application and have a structure 'Vertex' that I have defined in the common area at the top of my C program.
struct Vertex
{
int GblSeqNum;
int PlySeqNum;
struct Polyline *Line;
double CtrZ;
double x;
double y;
double z;
struct Edge *OwnerEdge;
struct Vertex *NextVtx;
struct Vertex *PrevVtx;
};
Next, right below the Vertex structure, I declare a global pointer to a Vertex structure:
struct Vertex *VtxsInLines;
Then, still in the common area, I use calloc to assign space for my vertices:
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
I compile the code using GNU C compiler using MinGW on Windows 10:
C:\000WORKIndexedTasks 000-999\500 Papers\523 PositionalAccuracyContourLines>gcc -c 523*.c
The following warnings and errors are generated:
523Paper_ReadContourVertices.c:98:1: warning: data definition has no type or storage class
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
^~~~~~~~~~~
523Paper_ReadContourVertices.c:98:1: warning: type defaults to 'int' in declaration of 'VtxsInLines' [-Wimplicit-int]
523Paper_ReadContourVertices.c:98:1: error: conflicting types for 'VtxsInLines'
523Paper_ReadContourVertices.c:47:16: note: previous declaration of 'VtxsInLines' was here
struct Vertex *VtxsInLines;
^~~~~~~~~~~
523Paper_ReadContourVertices.c:98:15: warning: initialization of 'int' from 'struct Vertex *' makes integer from pointer without a cast [-Wint-conversion]
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
It appears my declarations are in error somehow and this leads the compiler to assume an int type. This generates lots of errors later such as:
523Paper_ReadContourVertices.c: In function 'main':
523Paper_ReadContourVertices.c:432:20: error: invalid type argument of '->' (have 'int')
(VtxsInLines+idx)->GblSeqNum = -1;
Can you tell me with what what I provided what I am doing wrong?
The problem is that you are allocating the Vertex structure in the global space. It is not permissible to run executable instructions in the global scope, only allowed in functions such as main. The fix would be to move the VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex))); statement into the main function. You would still be able to access the memory assigned to the VtxsInLines variable in other functions without having to pass it along because VtxsInLines is global.
trying to do object orientation in C, but I don't get it.
I want to have a struct with references to functions and itself. I have this before main, but the compiler complains. How do I work around it?
Compiler complains about:
"Initializer element is not constant", "unknown typename SENSOR_OBJECT"
void config_time_base(alt_u32, void*);
void init_measurement(QUEUE *q);
void read_accelerometerX(QUEUE *q);
void update(QUEUE *q);
typedef struct SENSOR_CLASS
{
char description[80];
alt_u32 x_origo;
alt_u32 y_origo;
alt_u32 time_base;
QUEUE queue;
QUEUE *q;
void (*configure_time_base)(alt_u32, SENSOR_OBJECT*);
void (*reset_samples_vector)(QUEUE*);
void (*read_sensor)(QUEUE*);
void (*update_graph)(QUEUE*);
SENSOR_OBJECT* this;
}SENSOR_OBJECT;
QUEUE q1,q2,q3,q4,q5;
QUEUE* q11 = &q1;
SENSOR_OBJECT accelorometerX =
{ "Accelerometer x",
50, 50,1,q1,q11,
config_time_base,
init_measurement,
read_accelerometerX,
update,
&accelorometerX
};
You have a mention of SENSOR_OBJECT before SENSOR_OBJECT is actually defined:
void (*configure_time_base)(alt_u32, SENSOR_OBJECT*); // <--- mentioned here
SENSOR_OBJECT* this; // <--- mentioned here
}SENSOR_OBJECT; // <--- defined here
This is not allowed.
The easiest way out is to separate the typedef and the struct definition:
typedef struct SENSOR_CLASS SENSOR_OBJECT;
struct SENSOR_CLASS { ...
The Initializer element is not constant error tells you you cannot initialize a field with a thing which is not a constant expression. In order to fix this, write a function that allocates a SENSOR_OBJECT and assigns (not initializes) its fields from the function parameters. This would be your implementation of a constructor.
On a tangentially related note, it doesn't make much sense to keep a this pointer in each object. In order to access this, you would have to know the address of the object, but that address always equals this.
On a less related note, keeping function pointers in the struct is somewhat a waste of memory. Consider keeping them in a separate vtable object (one per class) and having a pointer to that vtable in each instance of the class.
You are using the typedef while defining the type. At the place you use the type alias, the compiler don't know it so replace with:
struct SENSOR_CLASS *this;
or you can make a forward declaration of your type, like:
typedef struct SENSOR_CLASS SENSOR_OBJECT;
struct SENSOR_CLASS {
SENSOR_OBJECT *this;
};
I've been quite aways away from C and as I am diving back into it I have found myself hitting a roadblock. I have the following structure:
typedef struct{
char id;
struct S *children[SIZE];
}S;
In my code I initially declare an array of structs...
struct S arr[SIZE];
But when I get to this point of trying to allocate my first child for my first member of arr...
arr[0].children[0] = (S*)malloc(sizeof(S));
I get this warning: warning: incompatible implicit declaration of built-in function ‘malloc’ warning: assignment from incompatible pointer type [enabled by default]
On top of this I'm getting an error that doesn't sound very logical to me. I have the following function:
int foo(S *children[SIZE]);
but when I call this line....
foo(arr[0].children);
I get this note: note: expected ‘struct S **’ but argument is of type ‘struct S **’
which to me just sounds silly, it is expecting the argument it is getting and is upset about it.
Any help in explaining what I should be doing to properly allocate this memory and achieve the same idea would be very much appreciated.
There is no struct S, only S which is a typedef of anonymous structure.
Define struct S too:
typedef struct S {
char id;
struct S *children[SIZE];
}S;
Or:
typedef struct S S;
struct S {
char id;
S *children[SIZE];
};
And do avoid casting return of malloc in C:
arr[0].children[0] = malloc(sizeof(S));
For your first problem, you need to do:
#include <stdlib.h>
at the top of your program, in order to call malloc successfully.
The second problem (as also pointed out by others) is that struct S in your class definition refers to a different struct than S. In C, struct tags are in a different "namespace" than type names.
I want to define a vector of struct. This vector should have the elements : user and role.
struct UserToRole_S
{
char user[SERVAL_HTTP_MAX_LEN_USER_NAME + 1];
unsigned int role;
};
typedef struct UserToRole_S UserToRole
#define ENDROLE 5
static UserToRole user_role[6] =
{
{"user5", ADMIN},
{"user4", GUEST},
{"user3", GUEST},
{"user2", GUEST},
{"user1", ADMIN},
{"andreea", ENDROLE},
};
UserToRole const *usertoroleTable[2] =
{
&user_role,
NULL
};
extern UserToRole const *usertoroleTable[];
But then I get the error: initialization from incompatible pointer type
What is wrong with my code? Definition of the vector?
You are missing typedef, you can't use the bare name of a structure as a type name in C.
Either add:
typedef struct UserToRole_S UserToRole_S;
or use:
static struct UserToRole_S user_role[] =
and so on, i.e. replace the bare name with the full struct UserToRole_S type name.
I have a basic problem. I should know enough about pointers by now. The way I see it configData is the first link in a linked list (of the type struct config) while procNames is a pointer to the first link in a linked list of the type struct config. So if I want to say that procNames is equal to configData then I need to access the pointer that points to configData which is *configData. Anyhow I think I am missing something. Anyone sees the problem? Also, I get the next error: error: invalid type argument of unary ‘*’ (have ‘struct config’)
struct config_line {
char name[MAX_WORD];
int time;
};
struct config {
struct config_line *lines;
int count;
};
//global variable
struct config configData;
//local variable
struct config *procNames;
//the problem (done locally)
procNames = *configData;
I think you want
procNames = &configData;
This sets the pointer procNames to the address of the structure configData.
You can access the elements using either
procNames->count
procNames->lines[i].name // Pointer to the 1st char of the name in the i'th config_line structure
or
configData.count
configData.lines[i].name
Remember that, since lines is itself a pointer, you'll need to allocate memory for each config_line structure:
struct config_line thisLine; // Declare a structure
procNames->lines = &thisLine; // Point to it
or
// Declare a pointer to an array of structures, allocate memory for the structures
struct config_line *linePtr = malloc(NUM_STRUCTS * sizeof(struct config_line));
procName->lines[i] = *linePtr; // Points to 1st structure in the array
Based on your description of what you are trying to do, you need to take the address of configData (write &configData on the last line). What you are trying to do on the last line is dereference configData, which the compiler will not let you do since configData is not a pointer (it does not store an address inside).
The error message is fairly clear on this. Unary * takes a single pointer as an argument, but the argument used of type struct config, and not a pointer.