I am using struct with unsigned int bit-fields perfectly, but suddenly, after duplicating one of them, the compiler is losing its mind (it would seem). Here's my code:
typedef struct myStruct {
unsigned int myVar:1;
} myStruct; // my compiler requires TWO declarations of the name for typedef
myStruct myNewStructVar;
myNewStructVar.myVar = 0; // throws error that "myNewStructVar" is unknown to the compiler
What gives? Again, I have two versions of this EXACT thing and it works fine.
You can declare the variable as a global outside of function scope, but you can't have a separate line of code to set its value. Setting the value on a separate line is executable code rather than initialization, and is not permitted there.
If you want to initialize it at the point of declaration, try:
myStruct myNewStructVar = {0};
This should work where it is now.
Related
Given I'll return a large struct in a function like here:
#include <stdio.h>
// this is a large struct
struct my_struct {
int x[64];
int y[64];
int z[64];
};
struct my_struct get_my_struct_from_file(const char *filename) {
int tmp1, tmp2; // some tmp. variables
struct my_struct u;
// ... load values from filename ...
return u;
}
int main() {
struct my_struct res = get_my_struct_from_file("tmp.txt"); // <-- here
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
At the place marked by here, do I have to assume that this large struct is copied or is it likely that the compiler does something to avoid this?
Thank you
… do I have to assume that this large struct is copied…
No, of course you do not have to make that assumption. Nobody requires you to make that assumption, and it would be unwise to adopt the statement as an assumption rather than deriving it from known information, such as compiler documentation or inspection of the generated assembly code.
In the specific code you show, it is likely good compilers will optimize so that the structure is not copied. (Testing with Apple Clang 11 confirms it does this optimization.) But that is likely overly simplified code. If a call to get_my_struct_from_file appears in a translation unit separate from its definition, the compiler will not know what get_my_struct_from_file is accessing. If the destination object, res in this example, has had its address previously passed to some other routine in some other translation unit, then the compiler cannot know that other routine did not stash the address somewhere and that get_my_struct_from_file is not using it. So the compiler would have to treat the structure returned by get_my_struct_from_file and the structure the return value is being assigned to as separate; it could not coalesce them to avoid the copy.
To ensure the compiler does what you want, simply tell it what you want it to do. Write the code so that the function puts the results directly in the structure you want to put it in:
void get_my_struct_from_file(struct my_struct *result, const char *filename)
{
…
}
...
get_my_struct_from_file(&res, "tmp.txt");
At the place marked by here, do I have to assume that this large struct is copied or is it likely that the compiler does something to avoid this?
Semantically, the structure is copied from the function's local variable to the caller's variable. These are distinct objects, and just like objects of other types, setting one structure equal to another requires copying from the representation of one to the representation of the other.
The only way to avoid a copy would be for the compiler to treat the local variable as an alias for the caller's structure, but that would be wrong in the general case. Such aliasing can easily produce observably different behavior than would occur without.
It is possible that in some specific cases, the compiler can indeed avoid the copy, but if you want to ensure that no copying happens then you should set up the wanted aliasing explicitly:
void get_my_struct_from_file(const char *filename, struct my_struct *u) {
int tmp1, tmp2; // some tmp. variables
// ... load values from filename into *u
}
int main() {
struct my_struct res = { 0 };
get_my_struct_from_file("tmp.txt", &res);
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
UPDATE: Code is correct and sensible, comments provide how to assign values to struct variables
I am writing a struct in C that contains 2 integer arrays and an array of custom-defined type 'info'. This 'info' type just contains several int variables. Here is the piece of code that I've come up with having done a bit of searching around the web:
typedef struct info {
int test_count;
int skip_count;
int prime_count;
} info;
struct myStruct {
int arr1[10];
int arr2[20];
info info[20];
};
This does not generate any compiler warnings or errors, but is it the most sensible implementation given what I'm trying to do?
Also– How would I assign values to the info variables and then access them through myStruct? I've tried various statements using the dot operator, but I cannot get them past the compiler.
Looks OK to me. Example usage struct myStruct x; x.info[3].skip_count = 4;
– M.M
And given: struct myStruct x; you should be able to use x.info[13].prime_count to access an element of that array.
– Jonathan Leffler
I'm taking over a piece of code..c programming in linux. I did a small change to a struct
typedef struct {
unsigned int a1;
..
..
..
float f1;
unsigned int a2;
unsigned int a3;
unsigned int offending; // shifted this
} test;
I shifted unsigned int offending to before float f1, like this:
typedef struct {
unsigned int a1;
..
..
..
unsigned int offending;
float f1;
unsigned int a2;
unsigned int a3;
} test;
and the code crashes... what could be the problem?
Is the order of members of a c struct important?
What could be the problem? Depend on the rest of the code, and what else you did.
No, the order of members of a struct is not intrinsically important. It is made so when other code depends on it.
Possible causes (not exhaustive):
You didn't recompile everything and there is external linkage on this struct or some aspect of it.
By moving the member you changed the alignment of other members and/or the sizeof() the struct, and didn't compensate for that.
There is a literal constant or macro somewhere with a size or offset that depends on this struct.
There is faulty code which never failed before but does now because of a change in memory layout.
The struct is used somewhere as part of another struct or union, and the problem is related to that.
There is a list initialisation using {} that no longer matches the member order.
You really should provide details of how it crashes. Otherwise it guesswork. And perhaps even then.
edit: ht #Jens.
The most probable reason for crashes if you change data layout is initialization. If you have old-time initializers in your code that use declaration order, all of a sudden the fields will receive different values than before. Therefore modern C since C99 has designated initializers that avoid that problem:
test toto = { 32, ... , 42, }; // sensible to reordering
test tata = { .a1 = 32, ... , .offending = 42, }; // still the same
Consider the following struct defined in ModuleA:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
If I wanted to use this struct from ModuleB, then I would declare the struct in the ModuleA header like this:
extern myStructType MyStruct;
So far, so good. Other modules can read and write MyStruct by including the Module A header file.
Now the question:
How can I declare only part of the struct in the Module A header file? For example, if I wanted ModuleB to be able to read and write MyStruct.C (or, to make things a bit easier, perhaps MyStruct.A or MyStruct.B), but not necessarily know that it's in a struct or know about elements A and B.
Edit: I should probably also specify that this will go in an embedded system which does basically all of its memory allocation at compile time, so we can be extremely confident at compile time that we know where MyStruct is located (and it's not going to move around).
Edit2: I'll also clarify that I'm not necessarily trying to prevent other modules from accessing parts of the struct, but rather, I'm attempting to allow other modules to access individual elements without having to do MyStruct.Whatever because other modules probably only care about a single element and not the whole structure.
You would have to encapsulate it, i.e. make a private variable such as:
static myStructType the_struct;
in some C file, and then provide an API to get access to the parts:
int * getC(void)
{
return the_struct.C;
}
this would then let other C files get access to an integer array by calling
int *some_c = getC();
some_c[0] = 4711;
or whatever. It can be made "tighter" by being more explicit about the length of the returned array of course, I aimed for the minimal solution.
While in theory there might be some problems with the cleanliness of this solution (e.g. structure alignment), in practice it usually works if it compiles and if it doesn't compile, you can alter the structures to make it compile:
#include <stddef.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
// You keep this definition private to module A (e.g. in a .c file):
typedef struct
{
int A;
int B;
int C[4];
} PrivateStruct;
// You expose this definition to all modules (in an .h file):
typedef struct
{
char reserved[2*sizeof(int)];
int C[4];
} PublicStruct;
// You put these in module A (in a .c file):
C_ASSERT(sizeof(PrivateStruct) == sizeof(PublicStruct));
C_ASSERT(offsetof(PrivateStruct,C) == offsetof(PublicStruct,C));
int main(void)
{
return 0;
}
In the public .h file you can lie to the world about the global variable type:
extern PublicStruct MyStruct; // It's "PrivateStruct MyStruct;" in module A
If the two structure definitions go out of sync, you get a compile-time error (match, mismatch).
You will need to manually define the size of the reserved part of PublicStruct, perhaps by trial and error.
You get the idea.
To make the long story short — you can't. To make it a bit longer, you can't reliably do it.
You could try to use a kind of getter:
in ModuleA:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
int getA()
{
return MyStruct.A;
}
and so on.
Instead switch over to c++
You can't do exactly what you've described but it's common to have a struct used as a header, which is contiguous with a buffer which has it's internals only known to a particular module.
It's fairly obvious what this struct is the header for, but it still works as an example:
typedef struct _FILE_NOTIFY_INFORMATION {
ULONG NextEntryOffset;
ULONG Action;
ULONG NameLength;
ULONG Name[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
This struct (from Microsofts NativeSDK) is designed to be the header of a variable length buffer. All modules can work out how long the buffer is by looking at NameLength but you could use this method to store anything in the buffer which goes with it. That might only be known by a particular module with the others just using the length to copy it etc..
If it not for hiding but for structuring, then do structure it. For example like so:
moduleA.h:
typedef struct{
int A;
}myStructModuleAType;
extern myStructModuleAType myStructModuleA;
moduleA.c:
myStructModuleAType myStructModuleA;
moduleB.h:
typedef struct{
int B;
}myStructModuleBType;
extern myStructModuleBType myStructModuleB;
moduleB.c:
myStructModuleBType myStructModuleB;
main.h:
#include "moduleA.h"
#include "moduleB.h"
typedef struct{
myStructModuleAType * pmyStructModuleA;
myStructModuleBType * pmyStructModuleB;
int C[4];
}myStructType;
extern myStructType myStruct;
main.c:
#include "main.h"
myStructType myStruct;
myStructType myStruct = {
.pmyStructModuleA = &myStructModuleA
.pmyStructModuleB = &myStructModuleB
};
I declared a Normal Structure In C:
typedef struct arr_struct{
int* original;
int size;
int first[size/2];
int second[size-(size/2)];
};
when compile it gives me:
test.c:11: error: ‘size’ undeclared here (not in a function)
any explanation?
You can't define arrays based on a variable size. The size has to be known at compile time. You'll need to make first and second pointers and dynamically allocate them once size is known.
You're getting the error message because you're trying to use the size member of the struct illegally. For one thing, the struct type definition isn't complete until the closing }, so until then the compiler doesn't know that there's a size member within the struct. For another, you cannot refer to a struct member without a struct instance; when you used the expression size the declarators for first and second, the compiler was looking for a variable named size outside of the struct definition.
It is possible to use a VLA within a struct type, but that's really not the approach you want to take here if you're doing what I think you're doing. Better to make first and second pointers to int and allocate them as necessary (as demonstrated by a couple of the answers above).
int val;
scanf("%d",&val);
int a[val];
The above code actually compiles and runs in my gcc compiler.
The reason for not working inside a struct could be due to the lining up of elements inside a struct whose size can't be determined at compile time. I am not fully sure about it though.
An implementation and usage for what miked said could be (without error checking):
typedef struct
{
int size;
int* first;
int* second;
} arr_struct;
// Prepare an arr_struct for use.
arr_struct foo;
foo.size = 1337;
foo.first = malloc(sizeof(int)*foo.size);
foo.second = malloc(sizeof(int)*(foo.size-foo.size/2));
Do remember to free(foo.first) and free(foo.second) when you're done, though!
The size you provide for an array needs to be a constant expression. You have a couple of choices. One would be to include a couple of pointers, and allocate the space dynamically:
typedef struct {
int* original;
int size;
int *first;
int *second;
} arr_struct;
Another possibility would be to use only one array, and create a pointer to the proper point in it:
typedef struct {
int* original;
int size;
int *second;
int first[];
} arr_struct;
This uses a flexible array member, which is new with C99 -- if you're using an out of date C compiler (e.g., MS VC++) it might not be supported directly1. In any case, this still requires dynamic allocation, but lets you do one large allocation for all the data instead of three separate allocations (one for the struct, and one each for first and second).
arr_struct *my_struct = malloc(sizeof(*my_struct) + size * sizeof(int));
my_struct->second = my_struct->first + size/2;
As an aside, note the syntax for typedef -- as it was, your typedef wasn't defining a name at all.
1The workaround is trivial though -- just define first with a size of 1 and subtract 1 from size in your allocation:
arr_struct *my_struct = malloc(sizeof(*my_struct) + (size-1) * sizeof(int));
In theory, this isn't required to work, but in fact it's just fine with all real compilers, at least AFAIK.