Defining structs in C after main() function - c

I have learned a decent amount of java and now I want to learn C, I've learned a little about structs and typedefs but I have errors when I place the typedef after the main() function and it is used from within the main() function.
Is there a way to declare types but not define them in C so I can keep my code after the main() function similar to functions? (I'm not sure if this is good practice but I like organizing my code this way)

Don't do that. C code is intended to be read by the compiler and it will learn about new definitions as it keeps reading the file. Moving things below main() serves no purpose. It will also confuse other humans.
As for the question itself: in some cases, yes, you can. If everything you need is a forward declaration, you can do so. But in most cases you will want the definition, so it won't help you.
For example, this will compile:
struct T;
int main(void)
{
struct T * p = 0;
return !!p;
}
// Later on you may define `struct T`

C requires a type to be declared before it's used. If the code is just using a pointer to the type then the code doesn't not need to declare the members, this is a forward declaration. Other usage, such as passing the type by value or using it as a local variable requires a full definition.
C projects generally use headers which will provide the definition of types. These are included into the C modules.
// header.h
#ifndef _header_h_
#define _header_h_
struct DescribedType {
int member;
char* variables;
};
#endif
// module.c
#include "header.h"
struct ForwardDeclaration;
ForwardDeclaration* allocForward();
int main(){
DescribedType someType;
ForwardDeclaration* someValue = allocForward();
return 0;
}
struct ForwardDeclaration {
int declaredLater;
};

Related

How does linking work in C with regards to opaque pointers?

So, I've been having a bit of confusion regarding linking of various things. For this question I'm going to focus on opaque pointers.
I'll illustrate my confusion with an example. Let's say I have these three files:
main.c
#include <stdio.h>
#include "obj.h" //this directive is replaced with the code in obj.h
int main()
{
myobj = make_obj();
setid(myobj, 6);
int i = getid(myobj);
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
struct obj *make_obj(void){
return calloc(1, sizeof(struct obj));
};
void setid(struct obj *o, int i){
o->id = i;
};
int getid(struct obj *o){
return o->id;
};
obj.h
struct obj;
struct obj *make_obj(void);
void setid(struct obj *o, int i);
int getid(struct obj *o);
struct obj *myobj;
Because of the preprocessor directives, these would essentially become two files:
(I know technically stdio.h and stdlib.h would have their code replace the preprocessor directives, but I didn't bother to replace them for the sake of readability)
main.c
#include <stdio.h>
//obj.h
struct obj;
struct obj *make_obj(void);
void setid(struct obj *o, int i);
int getid(struct obj *o);
struct obj *myobj;
int main()
{
myobj = make_obj();
setid(myobj, 6);
int i = getid(myobj);
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
struct obj *make_obj(void){
return calloc(1, sizeof(struct obj));
};
void setid(struct obj *o, int i){
o->id = i;
};
int getid(struct obj *o){
return o->id;
};
Now here's where I get a bit confused. If I try to make a struct obj in main.c, I get an incomplete type error, even though main.c has the declaration struct obj;.
Even if I change the code up to use extern, It sill won't compile:
main.c
#include <stdio.h>
extern struct obj;
int main()
{
struct obj myobj;
myobj.id = 5;
int i = myobj.id;
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
So far as I can tell, main.c and obj.c do not communicate structs (unlike functions or variables for some which just need a declaration in the other file).
So, main.c has no link with struct obj types, but for some reason, in the previous example, it was able to create a pointer to one just fine struct obj *myobj;. How, why? I feel like I'm missing some vital piece of information. What are the rules regarding what can or can't go from one .c file to another?
ADDENDUM
To address the possible duplicate, I must emphasize, I'm not asking what an opaque pointer is but how it functions with regards to files linking.
Converting comments into a semi-coherent answer.
The problems with the second main.c arise because it does not have the details of struct obj; it knows that the type exists, but it knows nothing about what it contains. You can create and use pointers to struct obj; you cannot dereference those pointers, not even to copy the structure, let alone access data within the structure, because it is not known how big it is. That's why you have the functions in obj.c. They provide the services you need — object allocation, release, access to and modification of the contents (except that the object release is missing; maybe free(obj); is OK, but it's best to provide a 'destructor').
Note that obj.c should include obj.h to ensure consistency between obj.c and main.c — even if you use opaque pointers.
I'm not 100% what you mean by 'ensuring consistency'; what does that entail and why is it important?
At the moment, you could have struct obj *make_obj(int initializer) { … } in obj.c, but because you don't include obj.h in obj.c, the compiler can't tell you that your code in main.c will call it without the initializer — leading to quasi-random (indeterminate) values being used to 'initialize' the structure. If you include obj.h in obj.c, the discrepancy between the declaration in the header and the definition in the source file will be reported by the compiler and the code won't compile. The code in main.c wouldn't compile either — once the header is fixed. The header files are the 'glue' that hold the system together, ensuring consistency between the function definition and the places that use the function (references). The declaration in the header ensures that they're all consistent.
Also, I thought the whole reason why pointers are type-specific was because the pointers need the size which can vary depending on the type. How can a pointer be to something of unknown size?
As to why you can have pointers to types without knowing all the details, it is an important feature of C that provides for the interworking of separately compiled modules. All pointers to structures (of any type) must have the same size and alignment requirements. You can specify that the structure type exists by simply saying struct WhatEver; where appropriate. That's usually at file scope, not inside a function; there are complex rules for defining (or possibly redefining) structure types inside functions. And you can then use pointers to that type without more information for the compiler.
Without the detailed body of the structure (struct WhatEver { … };, where the braces and the content in between them are crucial), you cannot access what's in the structure, or create variables of type struct WhatEver — but you can create pointers (struct WhatEver *ptr = NULL;). This is important for 'type safety'. Avoid void * as a universal pointer type when you can, and you usually can avoid it — not always, but usually.
Oh okay, so the obj.h in obj.c is a means of ensuring the prototype being used matches the definition, by causing an error message if they don't.
Yes.
I'm still not entirely following in terms of all pointers having the same size and alignment. Wouldn't the size and alignment of a struct be unique to that particular struct?
The structures are all different, but the pointers to them are all the same size.
And the pointers can be the same size because struct pointers can't be dereferenced, so they don't need specific sizes?
If the compiler knows the details of the structure (there's a definition of the structure type with the { … } part present), then the pointer can be dereferenced (and variables of the structure type can be defined, as well as pointers to it, of course). If the compiler doesn't know the details, you can only define (and use) pointers to the type.
Also, out of curiosity, why would one avoid void * as a universal pointer?
You avoid void * because you lose all type safety. If you have the declaration:
extern void *delicate_and_dangerous(void *vptr);
then the compiler can't complain if you write the calls:
bool *bptr = delicate_and_dangerous(stdin);
struct AnyThing *aptr = delicate_and_dangerous(argv[1]);
If you have the declaration:
extern struct SpecialCase *delicate_and_dangerous(struct UnusualDevice *udptr);
then the compiler will tell you when you call it with a wrong pointer type, such as stdin (a FILE *) or argv[1] (a char * if you're in main()), etc. or if you assign to the wrong type of pointer variable.

How to capture a struct declaration in function

I have the following c code:
struct {
short s;
int n;
} variableName;
I want to write a function to capture this variable like so
void func(MyStruct* var){
//do stuff
}
func(&variableName);
I would like to do this without providing a definition for the struct. Is there a way to capture variableName?
No, you can't pass an "anonymous" struct into a function in C. You could of course define your function to accept the arguments individually:
void func(short s, int n) { ... }
Or you can define the MyStruct structure in a place that both the function and the calling code has visibility to. Note that the whole struct is passed by value (copy) when you do that, which may be the behavior you want here (or may not be).
You may be looking for something more like a "dictionary" or "associative array" or "hash" type that many other languages provide, with arbitrary key value pairs in it. Pure C does not have a facility for this; the compiler wants to know the layout of a structure in advance.
(I'm not sure if you might be asking about a slightly more esoteric idea, which is hiding the composition of a structure and passing around an "opaque handle" out of and into an API. There are ways to structure that in C, but please say so if that's what you're talking about.)
Completely overlooked "I would like to do this without providing a definition for the struct. Is there a way to capture variableName?" in the OP, unless it was edited after. The question makes less sense now, but heres how you could normally pass a struct to a function for future readers.
#include <stdio.h>
struct StructName{
short s;
int n;
};
void func(struct StructName struct_var){
printf("Param values are: %4X %4X\n", struct_var.s & 0xFFFF, struct_var.n & 0xFFFF);
}
int main(){
struct StructName struct_var;
struct_var.s = 0xDEAD;
struct_var.n = 0xBEEF;
func(struct_var);
}
//It looks like you are trying to use the definition as a variable. Here the definition is StructName and the variable is struct_var.
this sample code outputs:
Param values are: DEAD BEEF
If you use clang or gcc, you may be able to use typeof:
struct foo {
struct {
int i;
} anon;
} foo;
void do_something(typeof(foo.anon)* member) {
member->i = 1;
}
If there is no global instance of your type, you may be able to use typeof((struct foo){}.anon).
This comes with a lot of downsides. The most obvious ones are that:
it's not standard, and it ties you to clang/gcc
it's pretty darn ugly
it might not behave as you expect anyway
For instance, structurally-equivalent anonymous types do not have the same type, so in something like this:
struct foo {
struct {
int i;
} anon1;
struct {
int i;
} anon2;
} foo;
anon1 and anon2 both have a different type, meaning that typeof one of them cannot be used to refer to both.
In the long run, you will almost certainly find that it's worth naming the structures, especially if you use them as function arguments. For instance, if you want to make your variable available from a header, I think that you'll have to work pretty hard to keep it anonymous.
Although it's not particularly pretty and not compatible with C++, C puts the name of nested declarations in the global namespace, so this is portable and it's not a very big code change to front-load:
struct {
struct not_anon {
int i;
} anon;
} foo;
void do_something(struct not_anon* member) {
member->i = 1;
}

How to declare global variable for an anonymous structure in C?

I am using Pelles C on Windows 8.1.
How to declare single global variable for a structure in C?
Code 1: it works but I do not want any other object of the same type to be created. If code 2 has problems then I will have to use this one.
Single.h
struct single{
int x;
};
extern struct single oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Code 2: It works but I am not clear about the combination of declaring and defining a variable in a header file. Will it cause a problem? I get no error though.
Single.h
struct{
int x;
}oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c is the same as in Code 1.
Can I use code 2 without any problem?
Can someone tell me why does code 2 work, when I and many others thought that it would not?
Thanks to everyone for all your comments and ideas and answers
There is a third variant which might be of interest.
It "hides" the struct single completely in Single.c. Hence, no accidental access is possible.
Single.h:
void initSingle(void);
void printSingle(void);
Single.c:
#include <stdio.h>
#include "Single.h"
struct Single {
int x;
};
static struct Single oneAndOnly;
void initSingle(void)
{
oneAndOnly.x = 10;
}
void printSingle(void)
{
printf("x = %d\n", oneAndOnly.x);
}
main.c:
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Live Demo on Wandbox
Actually, this approach is similar to P__J__'s answer. I just was too slow to press the Send button.
I needed some time to realize that the solution in quest should prevent an (accidental) second variable of the type of oneAndOnly.
"Hiding" the struct in the C file with a static instance is probably the best one can have in C. Even the counter examples in melpomene's answer shouldn't work in this case.
If read/write access to the single instance is required, I would add something like "getter"/"setter" functions.
This reminded me to the Singleton pattern though I'm not sure if that is a legal usage for a non-OO language like C. Googling a bit, I found (as well) How to create a Singleton in C? which I find worth to mention.
I googled a bit concerning the actual question of OP whether her/his Code 2 is valid as well. I suspected something like a duplicated definition (may be, because I did too long in C++ in daily work).
Actually, I tried OP's Code 2 in Wandbox – no duplicate definition issue. Finally, I found Are the global variables extern by default or it is equivalent to declaring variable with extern in global? and came to the conclusion that Code 2 should be fine as well.
The limitation is that Code 2 allows only default initialization (filling with 0s if I remember right). As soon as an initializer is added, the compiler complains (as expected) as it's included multiple times.
You call the function in other compilation unit. It uses the global variable not your main program. So you do not even have to know the data structure and the variable, as you newer use any of them in your main program.
you can reduce it to :
void initSingle(void);
void printSingle(void);
int main()
{
initSingle();
printSingle();
return 0;
}
and
#include <stdio.h>
struct{
int x;
}oneAndOnly;
static struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
None of your attempts will work in practice.
With e.g. gcc or clang I can just do
typeof(oneAndOnly) secondInstance;
gcc also supports
__auto_type secondInstance = oneAndOnly;
(not sure about clang).
Even if the compiler in question doesn't support these extensions, I can just copy/paste the anonymous struct declaration from the header.
That said, I don't see what preventing other objects of the same type buys you. It makes sense in Java to make the constructor private because a constructor has behavior whose use you may want to restrict, but in C structs are just dumb collections of data.

Acessing a locally declared struct outside of it's scope

I want to write data to an array of structures. The structure itself is declared and defined inside main(). I have 3 functions that need to write, process and read the data from the array.
All I could achieve was creating a global struct declaration and then passing pointers to them.
Is it possible without making the structure declaration global?
The relevant code is posted below.
This is my struct declaration outside of main()
struct date
{
int d;
int m;
int y;
};
struct stud
{
int roll;
char name[30];
struct date dob;
int P;
int C;
int M;
float PCM;
char flag_in;
char flag_pro;
};
These are the function defintions.
void getdata(struct stud *S)
{
scanf("%d", &(S->roll));
scanf("%s", (S->name));
//Similarly for dob, p, c, m
(S->flag_in)='1';
return;
}
void process(struct stud *S)
{
if(S->flag_in=='1')
{
S->PCM=(S->P + S->C + S->M)/3;
S->flag_pro='1';
}
}
void display(struct stud *S)
{
for(int x=0; x<10; x++)
if(S[x].flag_in=='1')
{
//printing the data to the console output
}
}
These are the function calls:
getdata(&S[i]);
process(&S[x]);
display(S);
It's entirely valid to not want to expose other parts of your program to the internal structure of a type.
C is extremely well placed to do this with considerable elegance.
Call this X.h
//Declaration of X as pointing to an incomplete struct XS.
//This says there's such a thing as a struct XS but not how it is laid out or even how big it is.
//It also says X is a short-hand for a pointer to a mysterious XS structure.
typedef struct XS* X;
//Creates an X and returns a pointer to it. Remember to call destroyX(.) exactly once - later.
X createX(void);
//Does something with X and returns some number.
int doXThing(X x);
//Destroys an X. Must be called exactly once for each return value from createX().
void destroyX(X x);
This is prog.c (containing your main(.) function).
#include <stdlib.h>
#include <stdio.h>
#include "X.h"
//Now we actually define that mysterious structure.
//Other translation units will not see this.
struct XS {
int v;
} ;
//Here we have size and layout so we can actually implement it.
X createX(void){
X x=malloc(sizeof(struct XS));//Explicit allocation of 'implementation struct'.
if(x==NULL){
return NULL;//malloc(.) failed.
}
x->v=0;
return x;
}
int doXThing(X x){
return (x->v)++;
}
void destroyX(X x){
free(x);
}
int main(void) {
X x=createX();
printf("%d\n",doXThing(x));
printf("%d\n",doXThing(x));
printf("%d\n",doXThing(x));
destroyX(x);
return 0;
}
Notice that the other modules using #include "X.h" don't see the layout of the structures.
The upside is the implementation can change normally without recompilation - just re-linking.
The downside is that without access to the size and layout of X those 'using' modules need to delegate all the work to a module that does!
That means all Xs have to come of the free-store (or a static pool inside the implementing module..).
This model is really rather common and quite powerful as it allows for complete abstraction and data hiding.
If you're willing to do a load of casting you don't even need to 'reveal' the name XS.
typedef XSHandle* X;
Or even
typedef unsigned short* X; //Little used type... Illegal but works on most platforms - check your documentation of use char (bare, signed or unsigned).
But don't get led into:
typedef void* X;
In C. void* is so promiscuous in its casting you will get into trouble!
C++ however behaves far better about that.
PS: It's not normal to put the implementation in the same translation unit as main(.).
It's not wrong in a small project but it's not normal to get into quite so much abstraction in a small project.
PPS: A stated this method provides for a very high degree of OO programming. It may be of interest that Stroustrup made documented design decisions to NOT do this for all classes in C++ because it has a fixed and unavoidable overhead and he gave himself a 'zero-overhead principle' and wanted to provide a way of 'mixing' abstraction with direct access to object layout (allocation as local variable, direct access to members, inline functions,...).
I think he made the right decision as a language level decision for the intended use of C++. That doesn't make it a bad design pattern where appropriate.
What you could do is declare the struct inside the main. and pass the pointer when the functions are called:
//this code is inside main
struct stud arr[10]; // create an array for the struct
display(arr); //pass the pointer to function
since the main is called before the functions the data will not be deleted and will exist on the processing of other functions which can pass the pointer between them.
Although I suggest not to use this method if the functions are not for one purpose (change value, print, etc...). If the data struct is used as global declare it as global.
I have the impression that you are not clear on the difference between the definition of a struct type and an instance of that type.
To be able to work with a struct variable, your functions have to see the full type declaration, such that the compiler knows how the variable is structured and to access the different fields. But there is no need that they see the variable declaration as such. The variable can be accessed without problems through a pointer that you pass as argument.
If you have your structure within the main() then the scope of this structure is local to main()
Since structures are user-defined data-types it can't used as you try because this new type is just visible within the main()
So the functions which you have defined will not have visibility of the structure.
So in order to handle this the structure should be made global.
So a binary answer to your question
Is it possible without making the structure declaration global?
is NO
Is it possible without making the structure declaration global?
No, any functions needs a struct's definition to be visible (globally) for it to be useable. Otherwise, from the function's viewpoint, the invisible struct would be an undefined identifier.
Local structs will not be visible anywhere outside the function.
The more important question would be what do you save in making it local as opposed to global? One thing that comes to my mind is that compilation time might be faster since if declared global in a header where lot of TUs see it unnecessarily.

Initializing a Global Struct in C

What is the best way to accomplish the following in C?
#include <stdio.h>
struct A
{
int x;
};
struct A createA(int x)
{
struct A a;
a.x = x;
return a;
}
struct A a = createA(42);
int main(int argc, char** argv)
{
printf("%d\n", a.x);
return 0;
}
When I try to compile the above code, the compiler reports the following error:
"initializer element is not constant"
The bad line is this one:
struct A a = createA(42);
Can someone explain what is wrong? I'm not very experienced in C. Thanks!
struct A a = { .x = 42 };
More members:
struct Y {
int r;
int s;
int t;
};
struct Y y = { .r = 1, .s = 2, .t = 3 };
You could also do
struct Y y = { 1, 2, 3 };
The same thing works for unions, and you don't have to include all of the members or even put them in the correct order.
Why not use static initialization?
struct A a = { 42 };
The problem here is that global / file static variables in C must have a value known at compile time. This means you can't use a user defined function to initialize the value. It must be a constant expression
For curious people who also use MSVC:
In C it is possible to run initialization functions before main just as it is possible in C++ (of course it is, how would C++ do it if it wasn't possible in C), however it may be somewhat confusing if you haven't read how does your runtime library work.
Long story short:
#pragma section(".CRT$XIU",long,read)
int
init_func ()
{
// initialization
return 0; // return 0 is mandatory
}
__declspec(allocate(".CRT$XIU"))
int (*global_initializer)() = init_func;
So it's not as compact source text as in C++, but it can be done. Also, before using I recommend to understand PE format first, then read crt\src\crt0.c and crt\src\crt0dat.c (search for _cinit in both files) in your MSVC installation directory so you know what is going on.
You cannot invoke functions in static initialization like that. In your example, you can simply use:
struct A a = {42};
If you have a more complicated setup, you will need to provide a library construction and library destruction function that you force users of your library to call (assuming you want to be portable), or you will have to use C++ and take advantage of constructors/destructors, or you will have to take advantage of the non-standard and non-portable __attribute__((constructor)) to create a function that is run on startup to initialize it.
If you have more complicated setup, I would strongly advocate that you use C++:
class A
{
A(){
// can do initialization in the constructor
}
// ...
};
A a;
However, if you need to stick with pure C, the portable thing to do is use something like:
typedef void* mylibrary_attr_t;
typedef void* mylibrary_t;
#ifdef __cplusplus
# define EXTERNC extern "C"
#else
# define EXTERNC
#endif
EXTERNC int mylibrary_attr_init(mylibrary_attr_t*);
EXTERNC int mylibrary_attr_setparam1(mylibrary_attr_t,int);
EXTERNC int mylibrary_attr_setparam2(mylibrary_attr_t,double);
// .. more functions for various attributes used by library
EXTERNC void mylibrary_attr_destroy(mylibrary_attr_t*);
EXTERNC int mylibrary_init(mylibrary_t*,mylibrary_attr_t);
EXTERNC void mylibrary_destroy(mylibrary_t*);
// functions that use mylibrary_t
// ...
Basically, in the above, you would initialize your library with mylibrary_init and teardown your library using mylibrary_destroy. The functions using your library would require an initialized instance of mylibrary_t, and so the person who created the main function would be responsible for invoking mylibrary_init. It is also good to make the initialization function dependent on an "attributes" parameter that can be replaced with 0 or NULL as a default. That way, if you extend your library and need to accept configuration options, it is available to you. That's more a design than technical approach, though.

Resources