How to define a const struct to make a consant - c

I'm trying to make a const struct so I can use is values as constant
For this purpose I have write this code:
typedef struct __PIN{
GPIO_TypeDef GPIO;
uint16_t pin;
}__PIN;
const struct __PIN PA1 = {.GPIO=GPIOA,.pin=GPIO_PIN_5};
But When I compile it prompt me whit the following error:
"multiple definition of 'PA1' "
but it's only defined in this file!
in fact the its said that is defined first in the same file and line that prompt the error:
.../CUSTOM/GPIO_custom/GPIO_lite_s.h:27: multiple definition of `PA1'; .../CUSTOM/GPIO_custom/GPIO_lite_s.h:27: first defined here
what is going on?
should I do this on a different way?
additional info:
-this is the header of a library that Im making, I want this constant value to be accesible to all files that include this header.
-Im programming on a STM32 board (STM32F411CEU6) using STM32CubeIDE 1.10.1
-I included the main.h so I can use the uint8_t like variables
-this files is currently being included in 2 files, main.c and another .c file, deleting its include in either of those files seems to fix the problem, but I don't know why.
any help would be very much appreciated!

Related

Can't resolve C warning in STM32CubeIDE

Facing a a warning which I am not able to get rid of. I am using stm32 MCU and STM32CubeIDE with a standard C11 compiler. Array gpioOutPins is used by in a function call gpio.c file. This function which contains this function call is called from inOut.c file.
Please note that the inOut.c file is in User Application layer while the gpio.c file is in the Kernel (Core) section of the project tree as can be seen below. I was not able to accommodate the whole project tree in the snapshot.
I don't understand why this warning is generated.
Any help is appreciated. Thank you.
An array is deifned in a header file gpio.h:
static uint16_t gpioOutPins[GPIO_OUT_CH_NR] =
{
DOUT_OD_OUT4_Pin,
DOUT_OD_OUT6_Pin,
DOUT_OD_OUT5_Pin,
DOUT_OD_OUT7_Pin,
DOUT_LED_DISABLE_Pin,
DOUT_BUZZ_Pin,
DOUT_OD_OUT8_Pin,
DOUT_OD_OUT3_Pin,
DOUT_OD_OUT2_Pin,
DOUT_OD_OUT1_Pin,
DOUT_ALARM_Pin,
DOUT_12V_PWR_Pin,
DOUT_12V_PWR_Pin
};
The directory structure looks like this:
The warning generated by the compiler is this:
warning: 'gpioOutPins' defined but not used [-Wunused-variable]
Header (.h) files are not a good place to define global variables, because when they are included in source (.c) files, multiple independent copies of them come to existence. They share the same name, but they are actually different variables. And if they are not static, the linker rejects them because of multiple definitions.
Your inOutTask.c probably includes gpio.h header directly or indirectly, so another copy of gpioOutPins comes into existence, which is distinct from the one used in gpio.c. Because you don't use gpioOutPins in inOutTask.c, you get the warning.
The proper way is to move the definition into gpio.c, remove the static keyword, and add extern uint16_t gpioOutPins[GPIO_OUT_CH_NR]; to gpio.h

share type definitions in source files

I'm just new to this separating source files.
.
Is it possible to share the my type defined to any other source files?
.
.
.
This is my definitions in myTypeDef.h
typedef struct
{
int x, y, w, h;
short life;
}Man;
What if I create a new .h (named draw.h) file that will draw the image like this:
#include "myTypeDef.h"
void rendererFunction(Man *man);
Then I create a .c (named draw.c) file that will implement what's in draw.h like this:
#include "draw.h"
void rendererFunction(Man *man)
{
draw(man->x, man->y, man->w, man->y);
}
Then what if I also created a update.h (and update.c for implementation) file that will update his position? Do I really have to connect the draw.h to update.h just to get my type defined object? Or is there any other way of sharing type defined object without repeating the definition when I include the .h's in my main??
I hope someone can help me. Thanks
A common idiom in c header files are inclusion guards. These use the preprocessor to prevent things like multiple definitions. They look something like :
#ifndef MYMODULE_MYFILENAME_H
#define MYMODULE_MYFILENAME_H
.... Your definitions....
#endif
This allows you to always include the header containing what a given file is using, even if some other file happens to also include the header you need. Indeed this is good practice so that if later you refactor a header file to no longer include the file you need, some seemingly unrelated code doesn't start failing to compile.
In your update.h, just include "myTypeDef.h". Like what you do with draw.h and draw.c;
Or in your draw.h and update.h, just use sentence struct Man; to declare the struct. And in your draw.c and update.c use include "MyTypeDef.h".

Remove precompiler directive from .h header file

I'm facing a problem that I don't know how to solve.
Suppose the following typedef struct into a test.h header file:
typedef struct example_struct {
#ifdef CONFIG_A
int A;
#endif;
int B;
} example_struct_t;
I am compiling the code using this header file passing CONFIG_A to the GCC with -D option. This way I am able to include A member to the struct or remove if not needed for a given use case.
Now suppose I generate a shared library (.so) and I would like to distribute it. So, I have the .so library and the headers with precompiler directives. The problem is that I would like not to include the -DCONFIG_A in the program using the library, I mean, I would need to hold the options employed at the library compilation time not only in the source files (.c) but also in the header. That is to say, if a compile the library with -DCONFIG_A option I suppose that program using the library shouldn't include that option in compilation time.
Are the precompiled headers the solution for this problem or is there any other alternative (avoiding include a config.h header in every files defining precompiler directives)?
Thank you so much for the guidance.
You can "generate" the code for the structure definition and ship the generated definition alongside the corresponding library. One idea is to keep your structures in a header with no #includes, in which case you can run the C preprocessor on them to get a file with no #ifdefs (which you can then use to build and ship).
Another way is to do something special in your build system. For example CMake has #cmakedefine which you can use inside a C or C++ source file and then generate code from that.

C Abstract data type pointer - Program modularity

If some module depends from some other sub-module, either including it in its header or in its code file, And what if modules, besides contributing to the main program, are also mutually dependent?
The figure below schematically illustrates a situation in which module1.h/.c requires a sub-module module4.h, and module2 requires module3.
Each header file has their own typedef struct exemple:
typedef struct list * List;
and the source file related to the header files implement the struct like :
struct list {
unsigned length;
char * value;
};
I got another struct in a header file:
typedef enum {START, END, MIDDLE, COMMENTS, CONDITIONS} TypeListBal;
typedef struct bal * Bal;
and source file :
struct bal {
TypeListBal type;
List name; // Name of the bal
List attributes[]; // Array of type struct List
};
I've been reading a lot tonight and I'm not quite sure about one thing. If I'm just including the header file in the source file that I need in my case, I'm including list.h in bal.c cause my bal.c got a struct definition which as member of type List.
To make it work, do I have to put specific #INCLUDE in all my modules or will the job be done at the compilation?
I mean in make makefile, to have my bal.o object, it will look like:
bal.o: list.o bal.c bal.h
$(CC) -g -W -Wall -c list.o bal.c bal.h
So as soon the makefile try to compile bal.o, the compiler will see all the dependencies, and will be able to compile everything.
That's how I did understand but when I try this, I get:
error: dereferencing pointer to incomplete type
I'm guessing it's because in my bal.c file, I'm declaring variable of type struct List and the compiler doesn't have any ideas about struct List cause the definition of struct list is in the list.c file.
So the question again is: How do I connect everything to make it work?
Your header file is broken. This is an incomplete type:
typedef struct bal * Bal;
It needs the struct declaration to make it complete. That ought to be in the header file, too. If in C code you say *Bal without the complete type, the compiler gives up because it doesn't have any information about what this expression means, i.e. the fields of the struct.
There should be absolutely no problem with the dependency graph you're showing. You want to use guards to ensure header files are included only once. Then you can include one header from another, and the C preprocessor will "just work" as long as there are no cyclic dependencies. In your case, the header for e.g. module 4 would look like:
// module4.h
#ifndef MODULE_4_H_INCLUDED
#define MODULE_4_H_INCLUDED
#include "module1.h"
// all public type declarations for module 4 types
#endif // MODULE_4_H_INCLUDED
Make all the headers (including module1.h) similar, with their own guard definitions. Then the module 4 code:
// module4.c
#include "module4.h"
// Use module 4 types.
In general, if you need types given by a header file in some .c file, include it even if it would be included by dependencies between headers. The guards will generally ensure no redundancy.
Additionally, your idea of make dependencies is incorrect. E.g. to compile module4.c successfully to obtain module4.o, you need (of course) module4.c, module4.h, and module1.h. Those are the build dependencies. So the rule will be:
module4.o : module4.c module4.h module1.h
$(CC) -g -W -Wall -c module4.c
But you should not write specific rules like this. Make has built-ins and general rules that are simpler to use. And you can use gcc itself to generate the header file dependencies rather than tracking them manually (which can lead to all kinds of disaster). See the -M option.
If the compiler only sees:
typedef struct list * List;
in an included file, and no definition of struct list anywhere else, when the compiler compiles a particular *.c file, and if the code in the *.c file dereferences the List pointer to access the members of the List struct, an error will be reported because struct list has not been defined.
Just because the definition of struct list exists in some other file, somewhere else in the same directory, that's compiled separately, doesn't mean that the compiler will know what it is, when it is compiling this file.
Compilation of a single *.c file is a completely separate process from the compilation of any other *.c file, and the compiler will only see the definitions of structures, functions and other things, that are explicitly #included, or declared in the .c file directly, when compiling that particular file.

Can't compile multiple files for Arduino

I'm having an issue with compiling code for Arduino if the code is in multiple files. What I have been doing in the past is have a script concatenate the files in another directory and make the project there. I would like to be able to compile directly from my build folder without having to jump through hoops of making sure everything is defined in the right order, etc.
I'm using avrdude to compile from Linux command line, because the Arduino IDE doesn't work very well with my window manager. When I make with multiple files (with appropriate #include statements, I get errors of the following nature, but for all of my methods and variables.
./../lib/motor.ino:3:21: error: redefinition of ‘const long unsigned int MOVE_DELAY’
./../lib/motor.ino:3:21: error: ‘const long unsigned int MOVE_DELAY’ previously defined here
The only other place that MOVE_DELAY is used is inside the void loop() function, and it doesn't redefine it there. The code also compiles fine if concatenate it into one file and run make in that directory, but not if they are in separate files with includes.
I believe your problem is solvable by declaring the objects with the "extern" prefix or external. For example. I often use the SdFat library, in which it is included in both my main sketch and instanced in other libraries.
/**
* \file test.ino
*/
#include <SdFat.h>
#include <foo.h>
SdFat sd;
...
Where I also use the same object in other libraries, such as foo.h.
/**
* \file foo.h
*/
#include <SdFat.h>
extern SdFat sd;
...
If it was not for the prefix of "extern" it would error like yours, as "sd" can not exist twice. Where the extern prefix tells the linker don't make a new instantiation, rather link to the externally instance elsewhere.

Resources