Is it possible to declare a structure type that is only visible in the .c file which uses the structure? I know that by putting static in front of a external data object, you change the linkage of the variable to be internal. But is it possible to put static in front of the declaration of a new struct type, like the following?
static struct log{
...;
...;
};
typedef struct log log;
If it is not possible to make the structure type, say log as above, to be "private", does it mean that even though other source files do not know the existence of the name (which is log in my example) of the structure, accidental name collisions can still happen if they name some variables log (assuming I will link all object files) ?
EDIT: I am not familiar with how compiler/linker works. If there is a global variable name log, and the file that contains the global variable is linked to the sole source file in which structure log is defined, wouldn't that cause any confusion when linking, one log is a variable name while another log is a type name?
No. The only way to make a struct private is to only have its definition available in the files that use it -- don't put it in a common header file. If it's only used in one source file, then just define it in that source file, but if it's used in more than one source file, you have a tricky problem: you can define it in each source file, but that's fragile since you have to remember to change each instance of it when you make any changes; or, you can define it in a private header file, and make sure only those source files include the private header.
Name collisions in different source files are ok, as long as they don't try to interface with each other in any way. If you have a struct log defined in one file and a different definition of struct log in a different file, do not ever pass one log to the other. In C, the structure name doesn't become part of any symbol names in the object file -- in particular, there's no name mangling of function names to include the parameter types (like C++ does), since function overloading is illegal in C.
No. static is a storage type; it is not meaningful to apply it to a type outside a variable declaration.
If you don't want to define struct log in your header file, you don't have to. Simply writing the typedef as:
typedef struct log log;
is sufficient, so long as you only deal with log * pointers. However, you will need a full definition of the structure to declare a log (or take sizeof(log)), because the size of the structure depends on what it contains.
With regard to name collisions, keep in mind that structures and types are not managed by the linker. The linker only cares about globally visible symbols, such as functions and variables. That being said, you should probably apply a prefix to your type names (e.g, mylib_log_t) to avoid confusion, particularly because log is a math function in the standard library.
You have a reason to write this:
static int a;
Because it prevents the linker from combining it with a defined somewhere else.
The linker has nothing to do with structs, so there is no worries putting in different c files.
As long as its in different c files, there will be no name confusions.
This isn't possible in general. But I can think of a hack that might work on some compilers.
The reason why this is hard to do is because the C compiler needs to know what the structure looks like in order to generate calls to functions with instances of the structure as argument.
So, suppose that you define a library with the following header:
struct foo {
int32_t a, b;
};
foo make_foo(int arg);
foo do_something(foo p1, foo p2);
Then to compile a program which makes a call to do_something, your compiler usually needs to know what the structure foo is like, so that it can pass it as an argument. The compiler can do all sorts of weird things here, like passing part of the structure via registers and part via the stack, so it really needs to know what the structure looks like.
However, I believe that in some compilers, it is possible to give the indication that the structure should be passed entirely via the stack. For instance, the regparm(0) function attribute should work for GCC if you have i386 as your target architecture (docs).
In that situation, it should be possible to do something like this: create a 'public version' of the header file, and in that file, instead of laying out the full struct, you create an undiferentiated version of it:
struct foo {
uint8_t contents[SIZE_OF_STRUCT_FOO];
}
where SIZE_OF_STRUCT_FOO is whatever sizeof(struct foo) returns when you define the struct in the usual way. You are then basically saying that "foo" is a struct with SIZE_OF_STRUCT_FOO bytes. Then, as long as the calling convention treats these two structs in the same way, it should work.
Related
In my Kernel module, I have two very short C source files (the main file and a daq.c and daq.h file). The header file contains a number of variables and functions. When I compile the functions normally, by declaring the variable in the daq.h file:
volatile uint32_t *gpio;
I receive the following error:
error In function `.LANCHOR1':
daq.c:(.bss+0x50): multiple definition of `gpio'
This error is only solved by declaring the variable as static, as follows:
static volatile uint32_t *gpio;
The kernel module works fine but in this case I receive the following warning as a static declaration creates a separated copy on every file in which it is included:
warning: ‘gpio’ defined but not used [-Wunused-variable]: static volatile uint32_t *gpio;
I've tried to declare it extern or just simply declaring the variable as uint32_t *gpio instead of declaring it static but then I get a:
WARNING: "gpio" undefined!
followed by an "out-of-tree definition" message in the dmesg log when the module is inserted (and the module is not loaded).
So, in this case, how is the best way to proceed in order to declare the variable? Is it correct to declare it as:
static volatile uint32_t *gpio;
and just omit the "defined but not used" warning given by the compiler? I don't think just "omitting" the warnings is a good practice, especially when it comes to kernel modules.
Thanks in advance.
Your question is not very clear because a full context is missing; but anyway I think some advice can be given.
First, your sources will be used together with other files; those files define things you have to be aware of, otherwise things like multiple definition of 'gpio' come out. In this case (gpio), you must decide if you want to interact with the "other" gpio variable - if not, you must use another name (it is not mandatory, but it is better).
Second, you must understand how the C compiler works, especially if you interface with the kernel, which adds some mechanisms. In general, you don't want to define variables in a header (.h) file; instead, you do declare them, together with data types, macros, and function prototypes. In the source files (.c) you #include headers in order to use the declarations found in them.
Variables are defined in .c files, and made available to other modules through header files, if this is wanted. Otherwise, make them static and do not mention them in the header.
The difference between declaration and definition is this: a declaration tells the compiler "you will encounter (perhaps) this name, somewhere, which has the following properties"; a definition instead means "I create this name, with these properties, and this thing is exactly here.".
When more than a single piece of software are used together, often happens that one piece does something needed in another one... declaration are the way to let these pieces work together.
Hope this helps a little.
Not particularly experienced in C, chance made be responsible for a small microcontroller project.
So, i have a structure which resides on a file1.c. Its used by several functions in that file. It was defined as static volatile Structure struct right now.
The struct is declared static because i read on a book called "embedded system development coding reference guide" that "variables accessed by several functions defined in the same file shall be declared with static in the file scope". Well, its used by several functions, and i want it file based so i thought it matches that description. Volatile because it holds some AD reads from some ports.
I also have a file2.c which needs to access values of the same structure.
From my understanding my options are the following
on file1.h define that structure as extern and access
#include file1.h on file2.c and access it.
From my undestanding though,this will make the structure visible to
the whole file2.c even though only 1 function there is going to need
it
keep the structure as is, and make a function in file.2 which accepts
the structure by reference function(Structure *struct), make that
function accessible from file1.c and just pass the value by ref
function(&struct)
Which one is the best approach? I know that both of them work, but is there a specific reason why i should use one and not the other etc?
I want to clarify that the typedef { variables } Structure, is in another header file which is included on both file1.c and file and file2.c, so there is no question about the files recognizing the structure. I am asking which is the best way to access that structure from where is needed.
You need to move the struct definition to an header file otherwise file2.c won’t recognize the struct even you pass it by reference . A reference or a pointer still need a class/struct definition to be compiled...
Based on your clarification, the struct should probably not be volatile qualified. Just because the actual ADC hardware registers are volatile, it doesn't mean that the data read from them has to be. Except if you fill the struct from an ISR or from DMA, but that doesn't sem to be the case(?).
The proper design is then to place the typedef of the struct in the header file and the variable definition in the .c file. Then provide access to the variable through getter/setter functions. However, consider if other code really need to access the struct as is, or if they just need a few values from it. Overall, use private encapsulation and stay away from extern.
I am aware that there are other questions about this which usually point to the standard solution of having both the struct and typedef struct declared and defined in the header file. However, I am looking at someone's else code which hasin the header:
struct A;
typedef struct A A_t;
Then the struct A is defined in *.c file together with the implementation of other functions. The implementation of A includes many defines, etc that are as well included in *.c not in the header.
Then in main.c the header is included and I have declared and defined new functions making use of (null) pointers to A_t which gives error dereferencing pointer to incomplete type when trying to access to a member of the struct.
Is there an alternative to declare and define the struct and typedef into the header for this case?
EDIT: Just to clarify that the original code foresees that the user creates some functions which are then passed to the main routines. For instance the user is supposed to create a function to connect to a socket, close a socket connection, transmit and receive data. Since I need an identifier/filedescriptor for the socket I have added an int to A's definition which is what I can't dereference. I hope this clarifies the context.
If someone has coded it like this and you assume that someone is a decent enough programmer, he might have done this on purpose.
In a proper C API design, you might have the need to expose a pointer to an internal data structure in order to be able to store context over function calls and expect your library user to receive that pointer from you, store it and hand it back with the next call into your library.
In this case, the most simple answer is: You are not expected to mess with this pointer, and you are not expected to allocate one of those structures yourselves nor dereference a pointer to it. X11 is a famous example of doing that.
If you actually need to be able to dereference such a pointer or access structure members, you need access to the full structure definition in some header file. Your choice where you want to put the definition, you can have more than one (i.e. there is no such thing as "the" header file) header.
Following your edit, I would propose you do it like so:
Apparently, the creator of your library has taken a lot of care to not expose the structure outside his module - I would leave it like that.
You need to add an int to the structure and have done so, so you obviously have access to the .c source. Do that, put it into the C file and leave the structure definition there. Add a setInt(struct A*, int) and a getInt(struct A*) function that allows you to set and retrieve the int from such an opaque pointer (getter and setter functions). Expose those 2 functions in the header of the C file. This leaves the original intention of the information hiding intact but still allows you to extend the structure.
You have two basic options:
Define the structure and all its members in a header file to be included in all the .c files that use this structure.
Leave the definition of the structure in a specific .c file which will also include the definitions of all the functions that access its members and those functions could be declared in a header file to be included in other .c files that need to manipulate the structure. Of course, you will still be able to use pointers to this structure in other .c files but you will not be able to access its members. This method may be viewed as is one of C's ways of providing sort of encapsulation or information hiding.
In my project, a structre is being used in several functions.
like this:
void function1 (Struct_type1 * pstType1);
but when I search for Struct_type1 's references, I can't find any. This Structure must be defined somewhere. How to find the definition?
OS- Windows
Edit: I think its difficult to answer this without source code and I can't share that big project here. So, I've changed my question to:
Is Hidden Declaration possible in an embedded project?
(by hidden I mean no one can see the definition.)
Is Hidden Declaration possible in an embedded project?
If you have access to all source code in the project, then no.
This is only possible in one specific case, and that is when you have an external library for which you don't have the C code, you only have a header file and an object file or lib file (or DLL etc).
For such cases it is possible (and good practice) for the library header to forward-declare an incomplete type in the header, and hide the actual implementation in the C file which you don't have access to.
You would then have something like this in the h file:
typedef struct Struct_type1 Struct_type1;
The compiler might often do things like this with its own libraries too, if they want to hide away the implementation. One such example is the FILE struct.
Not an answer, but possibly a way to find the answer. Idea: Let compiler help you.
Define the struct yourself, then look at compiler errors like "struct struct_type1 is already defined in... at line ..."
If you get no compiler error in this case, maybe the struct is only forward declared, but not defined.
To explain why this is sometimes done, here a bit of code:
// Something.h
struct struct_type1; // Forward declaration.
struct struct_type1 *SomethingInit();
void SomethingDo( struct struct_type1 * context );
In code looking like the above, the definition of the struct is hidden inside the implementation. On the outside, it need not be known, how the struct is defined or its size etc, as it is only traded as a pointer to the struct (and never as a value). This technique is used to keep internal types out of public header files and used often by library designers. You can think of it as an opaque handle of sorts.
But then, you still should be able to find the forward declaration, albeit not the definition.
if you want to cut to the chase, please skip down to the last two paragraphs. If you're interested in my predicament and the steps I've taken to solve it, continue reading directly below.
I am currently developing portions of a C library as part of my internship. So naturally, there are some parts of code which should not be accessible to the user while others should be. I am basically developing several architecture-optimized random number generators (RNG's)(uniform, Gaussian, and exponential distributed numbers). The latter two RNG's depend on the uniform generator , which is in a different kernel (project). So, in the case that the user wants to use more than one RNG, I want to make sure I'm not duplicating code needlessly since we are constrained with memory (no point in having the same function defined multiple times at different addresses in the code segment).
Now here's where the problem arises. The convention for all other kernels in the library is that we have a two header files and two C files (one each for the natural C implementation and the optimized C version (which may use some intrinsic functions and assembly and/or have some restrictions to make it faster and better for our architecture). This is followed by another C file (a testbench) where our main function is located and it tests both implementations and compares the results. With that said, we cannot really add an additional header file for private or protected items nor can we add a global header file for all these generators.
To combat this restriction, I used extern functions and extern const int's in the C files which depend on the uniform RNG rather than #define's at the top of each C file in order to make the code more portable and easily modified in one place. This worked for the most part.
However, the tricky bit is that we are using an internal type within these kernels (which should not be seen by the user and should not be placed in the header file). Again, for portability, I would like to be able to change the definition of this typedef in one place rather than in multiple places in multiple kernels since the library may be used for another platform later on and for the algorithms to work it is critical that I use 32-bit types.
So basically I'm wondering if there's any way I can make a typedef "protected" in C. That is, I need it to be visible among all C files which need it, but invisible to the user. It can be in one of the header files, but must not be visible to the user who will be including that header file in his/her project, whatever that may be.
============================Edit================================
I should also note that the typedef I am using is an unsigned int. so
typedef unsigned int myType
No structures involved.
============================Super Edit==========================
The use of stdint.h is also forbidden :(
I am expanding on Jens Gustedt’s answer since the OP still has questions.
First, it is unclear why you have separate header files for the two implementations (“natural C” and “optimized C”). If they implement the same API, one header should serve for either.
Jens Gustedt’s recommendation is that you declare a struct foo in the header but define it only in the C source file for the implementation and not in the header. A struct declared in this way is an incomplete type, and source code that can only see the declaration, and not the definition, cannot see what is in the type. It can, however, use pointers to the type.
The declaration of an incomplete struct may be as simple as struct foo. You can also define a type, such as typedef struct foo foo; or typedef struct foo Mytype;, and you can define a type that is a pointer to the struct, such as typedef struct foo *FooPointer;. However, these are merely for convenience. They do not alter the basic notion, that there is a struct foo that API users cannot see into but that they can have pointers to.
Inside the implementation, you would fully define the struct. If you want an unsigned int in the struct, you would use:
struct foo
{
unsigned int x;
};
In general, you define the struct foo to contain whatever data you like.
Since the API user cannot define struct foo, you must provide functions to create and destroy objects of this type as necessary. Thus, you would likely have a function declared as extern struct foo *FooAlloc(some parameters);. The function creates a struct foo object (likely by calling malloc or a related function), initializes it with data from the parameters, and returns a pointer to the object (or NULL if the creation or initialization fails). You would also have a function extern void FooFree(struct foo *p); that frees a struct foo object. You might also have functions to reset, set, or alter the state of a foo object, functions to copy foo objects, and functions to report about foo objects.
Your implementations could also define some global struct foo objects that could be visible (essentially by address only) to API users. As a matter of good design, this should be done only for certain special purposes, such as to provide instances of struct foo objects with special meanings, such as a constant object with a permanent “initial state” for copying.
Your two implementations, the “natural C” and the “optimized C” implementations may have different definitions for the struct foo, provided they are not both used in a program together. (That is, each entire program is compiled with one implementation or the other, not both. If necessary, you could mangle both into a program by using a union, but it is preferable to avoid that.)
This is not a singleton approach.
Just do
typedef struct foo foo;
These are two declarations, a forward declaration of a struct and a type alias with the same name. Forward declared struct can be used to nothing else than to define pointers to them. This should give you enough abstraction and type safety.
In all your interfaces you'd have
extern void proc(foo* a);
and you'd have to provide functions
extern foo* foo_alloc(size_t n);
extern void foo_free(foo* a);
This would bind your users as well as your library to always use the same struct. Thereby the implementation of foo is completely hidden to the API users. You could even one day to decide to use something different than a struct since users should use foo without the struct keyword.
Edit: Just a typedef to some kind of integer wouldn't help you much, because these are only aliases for types. All your types aliased to unsigned could be used interchangeably. One way around this would be to encapsulate them inside a struct. This would make your internal code a bit ugly, but the generated object code should be exactly the same with a good modern compiler.