I'm currently having an issue with the following struct:
typedef struct __attribute__((__packed__)) rungInput{
operation inputOperation;
inputType type;
char* name;
char numeroInput;
u8 is_not;
} rungInput;
I create multiple structs like above inside a for loop, and then fill in their fields according to my program logic:
while (a < 5){
rungInput input;
(...)
Then when I'm done filling the struct's fields appropriately, I then attempt to copy the completed struct to an array as such:
rungArray[a] = input; //memcpy here instead?
And then I iterate again through my loop. I'm having a problem where my structs seem to all have their name value be the same, despite clearly having gone through different segments of code and assigning different values to that field for every loop iteration.
For example, if I have three structs with the following names: "SW1" "SW2" SW3", after I am done adding them to my array I seem to have all three structs point me to the value "SW3" instead. Does this mean I should call malloc() to allocate manually each pointer inside each struct to ensure that I do not have multiple structs that point to the same value or am I doing something else wrong?
When you write rungArray[i] = input;, you are copying the pointer that is in the input structure into the rungArray[i] structure. If you subsequently overwrite the data that the input structure is pointing at, then you also overwrite the data that the rungArray[i] structure is pointing at. Using memcpy() instead of assignment won't change this at all.
There are a variety of ways around this. The simplest is to change the structure so that you allocate a big enough array in the structure to hold the name:
enum { MAX_NAME_SIZE = 32 };
…
char name[MAX_NAME_SIZE];
…
However, if the extreme size of a name is large but the average size is small, then this may waste too much space. In that case, you continue using a char *, but you do indeed have to modify the copying process to duplicate the string with dynamically allocated memory:
rungArray[i] = input;
rungArray[i].name = strdup(input.name);
Remember to free the memory when you discard the rungArray. Yes, this code copies the pointer and then overwrites it, but it is more resilient to change because all the fields are copied, even if you add some extra (non-pointer) fields, and then the pointer fields are handled specially. If you write the assignments to each member in turn, you have to remember to track all the places where you do this (that would be a single assignment function, wouldn't it?) and add the new assignments there. With the code shown, that mostly happens automatically.
You should malloc memory for your struct and then store the pointers to the structs inside your array. You could also turn your structs into a linked list by adding a pointer to each struct that points to the next instance of your struct.
http://www.cprogramming.com/tutorial/c/lesson15.html
Related
I am trying to initialize a struct of C array in go side.
I am new to cgo. Still trying to understand the use case.
test.h
typedef struct reply {
char *name;
reply_cb callback_fn;
} reply_t;
typedef struct common {
char *name;
int count;
reply_t reply[];
} common_t;
int
init_s (common_t *service);
test.go
name := C.CString("ABCD")
defer C.free(unsafe.Pointer(name))
num := C.int(3)
r := [3]C.reply_t{{C.CString("AB"), (C.s_cb)(unsafe.Pointer(C.g_cb))},
{C.CString("BC"), (C.s_cb)(unsafe.Pointer(C.g_cb))},
{C.CString("CD"), (C.s_cb)(unsafe.Pointer(C.g_cb))}}
g := C.common_t{
name: name,
count: num,
reply : r,
}
rc := C.init_s(&g)
I am getting error on "reply: r" unknown field 'r' in struct literal of type
Any help will be appreciated. The goal is initialize and then use it values in C init_s for processing.
You cannot use a flexible array field from Go: https://go-review.googlesource.com/c/go/+/12864/.
I think the reasonong is simple: this wart of C normally requires you to perform a trick of allocating a properly-aligned memory buffer long enough to accomodate for the sizeof(struct_type) itself at the beginning of that buffer plus sizeof(array_member[0]) * array_element_count bytes. This does not map to Go's type system because in it, structs have fixed size known at compile time. If Go would not hide reply from the definition, it would refer to a zero-length field you cannot do anything useful with anyway—see #20275.
Don't be deceived by code examples where a flexible array member field is initialized with a literal: as torek pointed out, it's a GCC extension, but what is more important, it requires work on part of the compiler—that is, it analyzes the literal, understands the context it appeared in and generates a code which allocates large enough memory block to accomodate both the struct and all the members of the flexible array.
The initialization of the array in your Go code may look superficially similar but it has an important difference: it allocates a separate array which has nothing to do with the memory block of the struct it's supposed to be "put into".
What's more Go's array are different beasts than C's: in C, arrays are pointers in disguise, in Go, arrays are first-class citizens and when you assign an array or pass it to a function call, the whole array is copied by value—as opposed to "decaying into a pointer"—in C's terms.
So even if the Go compiler would not hide the reply field, assignment to it would fail.
I think you cannot directly use values of this type from Go without additional helper code written in C. For instance, to initialize values of common_t, you would write a C helper which would first allocate a memory buffer long enough and then expose to the Go code a pair of pointers: to the beginning of the buffer (of type *C.common_t), and to the first element of the array—as *C.reply_t.
If this C code is the code you own, I'd recommend to just get rid of the flexible array and maintain a pointer to a "normal" array in the reply field.
Yes, this would mean extra pointer chasing for the CPU but it will be simpler to interoperate with Go.
I have an assignment for which the user will specify at run time the type of struct that they want to create.
For instance, lets say that the user inputs:
name : char[50], address: char[50] and age: int
Then my program will have to create a struct containing these 3 types of variables. Note that the user can specify as many variables as they want for the struct, only limiting them to char and int.
How should my code be in order to create a struct as specified above?
This is for c programming language only!
a variable have 3 fields:
1) type, 2) name, 3) address.
you shuold create an array of struct containing these 3, array of this struct will be what you want
your structs may look like this:
typedef enum _Type{T_INT,T_STRING}Type;
typedef struct _var{
Type type;
char* name;
union {int n; char* str;} data;
}var;
typedef struct _Struct{
int count;
var* array;
} Struct;
when you get the input, you need to build the Struct according to it.
name : char[50], address: char[50] and age: int
Struct *s = malloc(sizeof(Struct));
s->count = 3;//count of fields in the input
s->array = malloc(s->count*sizeof(var));
//you really should do it in a loop, after parsed the input...
for(i=0;i<s->count;i++){
s->array[i].name = strdup(parsedname);//"name", "address", "age"
s->array[i].type = strcmp(parsedtype,"int")?T_STRING: T_INT;
//for string you need to alloc memory for string...
if(s->array[i].type == T_STRING)
s->array[i].data.str=malloc(50 /*the size you've got*/);
//not need to alloc memory for the int
}
when you finish don't forget to free the mallocs:
for(i=0;i<s->count;i++){
free(s-array[i].name);
if(s->array[i].type == T_STRING)
free(s->array[1].data.str);
}
free(s->array);
free(s);
You'll also need a method to fill the struct and print it, and so on...
I have been wondering about this myself, because I was thinking about writing an FFI implementation for a language. (Although I suspect, based on your accepted answer, that your use case is somewhat different).
As pointed out, structs can only be generated at compile time, but this is primarily also a feature of the C language to enable type checking and so that type safety can be enforced.
At run time, you can still manipulate areas in memory as raw bytes. You just need to know the length and offset based on the individual components of the datatype you are declaring and manage these at accordingly.
I picked this up from looking at how the Ruby FFI library was implemented. The following is from their documentation:
When you call Struct.new, it allocs an “internal bytes” worth of
memory right then. When you then do a set, like struct[:member] = 3,
the bits within that struct are set right then. The inverse is also
true; x = struct[:member] does a read from the raw memory (and
translation into a ruby object), each time you access it. Memory is
“zeroed out” when it is first allocated, unless you pass in your own
Pointer or specify it to not clear memory (additional notes). If you
pass it a Pointer it basically uses that as its base instead of
allocating anything.
https://github.com/ffi/ffi/wiki/Structs#when-allocated
"only limiting them to char and int"
So you can create general datatype (struct), holding a list of nodes with name and char*, and a list of nodes with name and int.
On each new input you just fill the lists with required number of char* and int nodes.
To access the field of such data structure you'll need to traverse the list, although.
If you need efficiency, you can replace list to map (associative array). You'll need to implement it yourself as you are on C.
main.h
#define DATA struct data
DATA
{
int id;
char data;
}
main.c
DATA *listOfData[100];
So at this point I will/should be able to access DATA in the list like this:
printf(listOfData[5]->data);
It isn't letting me do it, the run just freezes on that last print f...no error or anything.
This is because you have defined an array of pointers. But you never initialized any of the pointers.
Therefore:
printf(listOfData[5]->data);
will crash (undefined behavior) because you are dereferencing the (invalid) pointer at index 5.
*(And that's a very odd way to define a struct...)
To fix this issue, you will need to allocate for each of the pointers in the array. If you don't actually need it to be an array of pointers, then it might be better to just make it array of the struct itself:
DATA listOfData[100];
and access it as:
listOfData[5].data
Then you don't have to deal with allocating each element.
I'm not sure why printf would just freeze, but there's a couple of things wrong with this. First, all the pointers in your DATA* array are uninitialized. You probably intended to make an array of DATA, instead of an array of DATA pointers:
DATA listOfData[100];
You also didn't end the struct with a semicolon, so it seems unlikely that this would even compile:
#define DATA struct data
DATA
{
int id;
char data;
};
Finally, you're using printf in a rather unsafe way; the first argument needs to be a format string, or you can get weird behavior if the first argument has a % in it:
printf("%c\n", listOfData[5].data);
You haven't shown any memory allocation for the DATA *. Either declare your array as an array of struct data, like:
DATA listOfData[100];
or allocate memory dynamically and assign the pointers in your array.
What is the benefit of declaring a C structure member as in array of size 1 instead of a pointer :
struct {
a_struct_t a_member[1];
...
}b_struct;
Thanks in advance
In a typical case, a structure with a member that's declared as an array of one item will have that member as the last item in the struct. The intent is that the struct will be allocated dynamically. When it is allocated, the code will allocate space for as many items as you really want/need in that array:
struct X {
time_t birthday;
char name[1];
};
struct X *x = malloc(sizeof(*x) + 35);
x->birthday = mktime(&t);
strcpy(x->name, "no more than 35 characters");
This works particularly well for strings -- the character you've allocated in the struct gives you space for the NUL terminator, so when you do the allocation, the number of characters you allocate is exactly the strlen() of the string you're going to put there. For most other kinds of items, you normally want to subtract one from the allocation size (or just live with the allocated space being one item larger than is strictly necessary).
You can do (sort of) the same thing with a pointer, but it results in allocating the body of the struct separately from the item you refer to via the pointer. The good point is that (unlike the method above) more than one item can be allocated dynamically, where the method above only works for the last member of the struct.
What you describe are two different things entirely. If you have a pointer as a member:
a_struct_t* a_member;
then it is simply a pointer. There is no memory allocated inside of the struct to hold an a_struct_t. If, on the other hand, you have an array of size 1:
a_struct_t a_member[1];
then your struct actually has an object of type a_struct_t inside of it. From a memory standpoint, it isn't much different from just putting an object of that type inside the struct:
a_struct_t a_member;
From a usage standpoint, an array requires indirection to access the one element (i.e., you need to use *a_member instead of a_member).
"Array of size 1 instead of a pointer"? Sorry, but I don't see how this quiestion can possibly make sense. I would understand if you asked about "array of size 1 instead of an ordinary member (non-array)". But "instead of a pointer"? What does pointer have to do with this? How is it interchangeable with an array, to justify the question?
If what you really wanted to ask is why it is declared as an array of size 1 instead of non-array as in
struct {
a_struct_t a_member;
} b_struct;
then one possible explanation is the well-known idiom called "struct hack". You might see a declaration like
struct {
...
a_struct_t a_member[1];
} b_struct;
used to implement an array of flexible size as the last member of the struct object. The actual struct object is later created within a memory block that is large enough to accomodate as many array elements as necessary. But in this case the array has to be the last member of the struct, not the first one as in your example.
P.S. From time to time you might see "struct hack" implemented through an array of size 0, which is actually a constraint violation in C (i.e. a compile error).
So I think it's been stated that the main difference between pointers and arrays is that you have to allocate memory for pointers.
The tricky part about your question is that even as you allocate space for your struct, if your struct contains a pointer you have to allocate a SECOND time for the pointer, but the pointer itself would be allocated as part of the struct's allocaiton.
If your struct contained an array of 1 you would not have to allocate any additional memory, it would be stored in the struct (which you still have to allocate).
These are different things.
Such member's name is an address of allocated memory, allocated inside the struct instance itself.
How to copy typedef struct into another one?
If I have a typedef struct called books and I have a struct variable called books first. Now I declare books second How can I pass the content of first to second? Is there a function to do that or I can do that just with second = first ?
If your structure does not contain any members that are pointers (or containing structs that do), then you can simply assign one to the other.
second = first;
If however your structs do contain pointers, then with a simple assignment you end up with two struct that contain pointers to the same memory, and changing one will affect the other. If that's not what you want then you need to do a deep copy.
For example:
struct book {
char *name;
int cost; // in cents, so you don't have to deal with floating point issues
};
struct book first;
first.name = strdup("title1");
first.cost = 500;
struct book second;
second.name = strdup(first.name);
second.cost = first.cost;
If both first and second have the same type, then you can just do second = first; . It does not matter whether the type is an built-in or user-defined. C will copy the contents of first over to second. Just try it.
In general, variables in C are just data with a name and a type.
If the types of 2 variables a and b match, you can assign one to the other: a = b;.
What happens is that the value of variable b is copied into variable a.
But beware of pointers: For C, pointers are just variables with a value (the fact that the value represents a memory address does not matter, C treats all data equal).
If the 2 variables happen to be pointers, like char *a; char *b; then you can assign a = b; just with any variable.
But since the value of the variable b is the memory address, the memory address is copied from b to a, not the content of the memory at the memory address.
If you want to have the memory copied over, you will have to do it on your own, e.g. via the help of memcpy() (see its man page for information).
That said, if your structs contain pointers, the pointers are the content, not the stuff the pointers point to. C would copy the pointer values, not the pointer targets.
If you got pointers in your structs and want some sort of deep-copy, you would have to implement the traversal of your structs on your own. See What is the difference between a deep copy and a shallow copy?