I am making a C program, which needs to access a struct array in a struct.
The definition looks like below
struct def_world
{
bool lock;
char tilemap;
def_tile tile[100][100];
struct def_tile
{
bool lock;
char kind;
def_obj * obj;
void * evt;
};
struct def_obj
{
bool lock;
int indexOfTable;
bool frozen;
char x,y;
char kind;
char face;
char * msg;
char * ip;
};
in the main function, I want to access world's tile[3][3]'s obj's face.
I initialize world as
def_world world={0,};
but the following lines make errors
world.tile[3][3].obj=newobj();//newobj() returns def_obj type
world.tile[3][3].obj->face;
any idea how to access obj's face?
Try these lines instead:
world.tile[3][3]->obj=newobj();//newobj() returns def_obj type
world.tile[3][3]->obj.face;
Explanation:
world.tile[3][3] is a def_tile. It's obj field isn't def_obj, but rather def_obj*. Therefore, to get the def_obj that it points to, you should use ->obj.
Inside def_obj, face is just a char, so you would access it with .face.
Related
How do I make this struct instruction visible to struct cpu state? Like If I put cpu state struct first it doesn't work because some other arguments won't be visible to struct instruction but if I put it reverse again I have a problem.
struct cpu_state
{
int nextinstructionlinenumber;
char filename[200];
char RLO;
struct instruction instructionlist[INSTRUCTIONLIST_SIZE];
int instructionlistnumber;
struct variable variablelist[INSTRUCTIONLIST_SIZE];
int variablelistnumber;
};
struct cpu_state CPU;
struct instruction{
char name[LINE_CHAR_NUM];
void(*function)(struct cpu_state* pstate, struct line* pline);
};
You can create incomplete structure declarations provided they are just used for pointers. For example, the following order will work. Note that I created a dummy definition for struct variable since it was absent from the post. You can replace it with whatever you like:
struct variable {
int dummy_val;
};
struct cpu_state;
struct line;
struct instruction{
char name[LINE_CHAR_NUM];
void(*function)(struct cpu_state* pstate, struct line* pline);
};
struct cpu_state
{
int nextinstructionlinenumber;
char filename[200];
char RLO;
struct instruction instructionlist[INSTRUCTIONLIST_SIZE];
int instructionlistnumber;
struct variable variablelist[INSTRUCTIONLIST_SIZE];
int variablelistnumber;
};
struct cpu_state CPU;
I have a problem with some of my functions. I want to get a member ob a struct, out of another struct. The normal call is functionel, but embedded in a function, it doesn't work. Is there any idea why and how I can solve that?
The following function is an example. It should get the time out of a struct, embedded in another struct via the time-converting function "FUN_1"
FUN_1((time_t *)&ptr_to_s_20b_parse_entries->s_28b_meta->time_c);
My structs are:
struct s_28b_meta {
int version;
__time32_t time_c;
__time32_t time_m;
uint32_t i_next;
int hash_value;
int len_database_name;
int *ptr_database_name;
};
struct s_20b_parse_entries {
int *s_28b_meta;
int *s_8b_keys;
int **a_db_entries;
size_t n_db_entries;
int i_next;
};
The decleration:
struct s_28b_meta *ptr_temp;
struct s_20b_parse_entries *ptr_to_s_20b_parse_entries;
In struct s_20b_parse_entries, you have the s_28b_meta field defined as int *. This is not a pointer to struct so you can't use the -> operator on it, which is why you're getting the error.
It should be defined as a struct s_28b_meta *.
Say we have an instance of
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
};
and we want to recreate it as an object of other type
struct CoreMessage {
int messaageId;
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
Can we safly turn Message A into CoreMessage B? thing in C without copying contents, having types partly overlaping as shown here?
You can fake this with anonymous structures/unions. Anonymous structures have admittedly only been standardized since C11 but many popular compilers have supported them as an extension for ages.
That is something along these, admittedly-less-than-pretty, lines:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
struct CoreMessage {
int messageId;
union {
struct Message;
struct Message message;
};
};
No, you cannot do what you ask. You could come close, however, if you were willing to change the layout of struct CoreMessage like so:
struct CoreMessage {
struct Message message;
int messaageId;
char * senderId;
int senderIdLength;
};
Note that struct CoreMessage then contains an actual struct Message as a member (as opposed to a pointer to one). Then, given ...
struct CoreMessage cm;
struct CoreMessage *cmp = &cm;
struct Message *mp = &cm.message;
... you have (void *) cmp == (void *) mp, which can be useful for some of the kinds of things you might want to do. This is also adjusts automatically to changes to struct Message.
Alternatively, you can do something like this:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
char resv2[AS_MANY_BYTES_AS_ANY_MESSAGE_TYPE_MAY_NEED_INCLUDING_PADDING];
};
struct CoreMessage {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
int messaageId;
char * senderId;
int senderIdLength;
};
struct Message msg;
struct CoreMessage *cmp = (struct CoreMessage *) &msg;
That has a high probability of working as you would hope (and some system interfaces work pretty much this way) but C does not guarantee that those corresponding elements will be laid out the same way in the two different struct types.
Note, too, that it was no accident that I moved CoreMessage.messageId after the members corresponding to those of struct Message. It is much harder to arrange for corresponding layout if you do not do this, and the pointer value equivalence of the first alternative depends on it.
Not sure what you mean by "safely turn", but I would expect the answer to be "no". The structures are different, of course the smaller one can't magically be expected to expand into memory it didn't previously use.
There is no concept of "overlapping types" in C.
You can of course declare CoreMessage in terms of Message, but it won't help for the reverse transform from the smaller to the larger type except by making the transfer of the shared information easier:
struct CoreMessage {
int messageId;
struct Message message;
char *senderId;
int senderIdLength;
};
Now if we have:
struct Message a = { ... }; /* fully initialized */
struct CoreMessage b; /* we want to convert Message into this */
we can do:
b.messageId = 4711;
b.message = a; /* Copy all Message data over. */
b.senderId = "foo";
b.senderIdLength = 3;
Nothing is automatic here though, you have to do it yourself.
I'm not sure exactly what you mean by "turn into". I'm not sure how you can get casting to do this for you.
But, the C standard allows the compiler to put unused space between fields of a struct so, in general nothing would really work. You could make "CoreMessage" contain a "Message" and produce your result with a single assignment.
I declare a new struct with the name of "Struct"
I have a generic function that takes in an argument "void *data".
void Foo(void *data)
I pass an instance of "Struct" into the generic function.
Struct s;
Foo(&s);
I want to access one of the properties of the struct in the function.
void Foo(void *data) {
char *word = (char*) data.word;
}
It's not allowed because it doesn't recognize data as a valid struct.
I even try to declare the data as the struct type first, and I get an error.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
I get "conversion to non-scalar type requested".
First of all, you should turn on your compiler's warning flags (all of them). Then you should pass a pointer to your Struct and use something other than struct as a variable name:
Struct s;
Foo(&s);
Then, in Foo:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
You can't convert non-pointer types to and from void* like you're trying to, converting pointer types to and from void* is, on the other hand, valid.
You need to pass a pointer to you struct and get a pointer to the struct inside the function:
Struct struct;
Foo(&struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
You have to use -> operator when requesting structure member via pointer.
This should work: char *word = (char*) data->word;
You also have to pass the address of the structure to the function. Like this: Foo(&struct);.
Firstly you need to call the function correctly:
Struct s;
Foo(&s);
Notice you're now passing a pointer to the structure.
Now, the function has to know that you're using a Struct (as opposed to something else) - perhaps because of another parameter, or a global variable, or some other reason. Then inside the function you can do:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Data is pointer, so whatever you cast it to must also be a pointer. If you said Struct* myStruct = (Struct*) data, all would be well with the world.
You are mixing pointers and data.
Struct struct defines a data object
void *data expects data to be a pointer.
Call Foo with a pointer to a Struct, and make other necessary changes
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
or the more compact form:
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}
I have a struct defined as:
struct {
char name[32];
int size;
int start;
int popularity;
} stasher_file;
and an array of pointers to those structs:
struct stasher_file *files[TOTAL_STORAGE_SIZE];
In my code, I'm making a pointer to the struct and setting its members, and adding it to the array:
...
struct stasher_file *newFile;
strncpy(newFile->name, name, 32);
newFile->size = size;
newFile->start = first_free;
newFile->popularity = 0;
files[num_files] = newFile;
...
I'm getting the following error:
error: dereferencing pointer to incomplete type
whenever I try to access the members inside newFile. What am I doing wrong?
You haven't defined struct stasher_file by your first definition. What you have defined is an nameless struct type and a variable stasher_file of that type. Since there's no definition for such type as struct stasher_file in your code, the compiler complains about incomplete type.
In order to define struct stasher_file, you should have done it as follows
struct stasher_file {
char name[32];
int size;
int start;
int popularity;
};
Note where the stasher_file name is placed in the definition.
You are using the pointer newFile without allocating space for it.
struct stasher_file *newFile = malloc(sizeof(stasher_file));
Also you should put the struct name at the top. Where you specified stasher_file is to create an instance of that struct.
struct stasher_file {
char name[32];
int size;
int start;
int popularity;
};
How did you actually define the structure? If
struct {
char name[32];
int size;
int start;
int popularity;
} stasher_file;
is to be taken as type definition, it's missing a typedef. When written as above, you actually define a variable called stasher_file, whose type is some anonymous struct type.
Try
typedef struct { ... } stasher_file;
(or, as already mentioned by others):
struct stasher_file { ... };
The latter actually matches your use of the type. The first form would require that you remove the struct before variable declarations.
the case above is for a new project. I hit upon this error while editing a fork of a well established library.
the typedef was included in the file I was editing but the struct wasn't.
The end result being that I was attempting to edit the struct in the wrong place.
If you run into this in a similar way look for other places where the struct is edited and try it there.
The reason why you're getting that error is because you've declared your struct as:
struct {
char name[32];
int size;
int start;
int popularity;
} stasher_file;
This is not declaring a stasher_file type. This is declaring an anonymous struct type and is creating a global instance named stasher_file.
What you intended was:
struct stasher_file {
char name[32];
int size;
int start;
int popularity;
};
But note that while Brian R. Bondy's response wasn't correct about your error message, he's right that you're trying to write into the struct without having allocated space for it. If you want an array of pointers to struct stasher_file structures, you'll need to call malloc to allocate space for each one:
struct stasher_file *newFile = malloc(sizeof *newFile);
if (newFile == NULL) {
/* Failure handling goes here. */
}
strncpy(newFile->name, name, 32);
newFile->size = size;
...
(BTW, be careful when using strncpy; it's not guaranteed to NUL-terminate.)
The reason is you did not declare type struct stasher_file, you define a struct variable stasher_file
instead.
In C, the declaration of structure:
struct structure-tag {
member1
member2
...
};
structure-tag is an optional name following the keyword struct.
After declaration, you can define a variable:
struct structure-tag var1, *var2;
Also, you can do both declaration and definition like:
struct structure-tag {
member1
member2
...
} var1, *var2;
So in your case, you could try this:
struct stasher_file {
char name[32];
int size;
int start;
int popularity;
} *files[TOTAL_STORAGE_SIZE];
struct stasher_file *newFile = malloc(sizeof(struct stasher_file));
... other code ...
That's all.