I have several 450 element character arrays (storing bitmap data to display on lcd screens.) I would like to put them under a header file and #define them, but I keep getting compilation errors. How would I do this in C?
#define numbers[450] {0, 1,etc...}
#define numbers {0, 1, etc...}
#define numbers[450] then set the numbers later
and many more...
Well... you certainly don't need to use a define. Just add them into the header as const, static arrays.
/* prevents multiple, redundant includes */
/* make sure to use a symbol that is fairly sure to be unique */
#ifndef TEST_H
#define TEST_H
/* your image data */
const char image[] = { 1, 2, 3, 4, ... };
#endif
Also, if you want help on a compilation error then you should post your code.
Because you are displaying on an LCD, I am assuming this is an embedded system.
Don't put the data into a header.
Put the data into an ordinary C or C++ file. Compile this. It might only contain the data, that is okay, and makes it easy to update.
Then use the header file to give access to the data.
For example, in a images.c file:
#include "images.h"
const byte numbers1[MAX_NUMBERS1] = { ... };
byte numbers2[MAX_NUMBERS2]; // will be initialsied to 0
Then images.h is:
#ifndef _IMAGES_H_
#define _IMAGES_H_
typedef unsigned char byte;
#define MAX_NUMBERS1 (450)
// different constants in case you change something
#define MAX_NUMBERS2 (450)
// even better if you can do const static int MAX_NUMBERS1=450;
// but depends on the compiler
extern const byte numbers1[MAX_NUMBERS1] = { ... };
extern byte numbers2[MAX_NUMBERS2]; // will be initialised to 0
#endif
Then all other .c files in the program can access them.
It is (almost) always a bad idea to put a definition of a variable into a header file.
A declaration of a variable, eg.
extern byte numbers2[MAX_NUMBERS2];
is telling the C compiler that there is an array variable called numbers2 somewhere else in the final, linked program. If the linker doesn't get that definition (from somewhere else) then it will raise an error because there is no space for the variable allocated.
A definition of a variable (notice no extern), eg.
byte numbers2[MAX_NUMBERS2];
is effectively telling the C compiler that there is an array variable called numbers2 and it should allocate the space here, in the resulting object code from this source file, and this will be used to hold the value of the variable in the final, linked program.
The space for numbers2 is not allocated by the C compiler when it sees a declaration (preceded by extern), it is allocated when it sees the actual definition (no extern).
So, if you put the actual definition of any variable in a header file, and include it into more than one source code files (.c), the C compiler will allocate space for the variable more than once. Then the linker will give an error (usually multiple definitions of the same name).
There is a more subtle problem. If, when first developing the program, the header file is only included is one source file, then the program will compile and link correctly. Then, at a later date, if a second source file includes the header (maybe someone has just split the original source code file into two files), the linker will raise a 'multiple definitions' error. This can be very confusing because the program used to compile and link, and apparently nothing has changed.
Summary
Never allocate space for a variable by putting a definition in a header file. Only put variable declarations in header files.
I have had a similar problem. In my case, I needed an array of constants in order to use as size of other static arrays. When I tried to use the
const int my_const_array[size] = {1, 2, 3, ... };
and then declare:
int my_static_array[my_const_array[0]];
I get an error from my compiler:
array bound is not an integer constant
So, finally I did the following (Maybe there are more elegant ways to do that):
#define element(n,d) ==(n) ? d :
#define my_const_array(i) (i) element(0,1) (i) element(1,2) (i) element(2,5) 0
Related
I have a global variable/buffer defined in a header. I have two source files, a function library (lib.c) and a test bench (tb.c), both include the header.
In the library, I fill the global variable buffer, print the pointer value and print some of the entries of the u8 buffer by iterating the pointer, i.e. [1, 2, 3, 4, 5 etc], with pointer 0xC8004C58 (buffer length = 2144).
Now in the test bench, I grab a pointer to this same global u8 buffer in exactly the same way. Now my interpretation is that the global variable remains in the same place so the pointer to its start should be the same, however instead I get pointer 0xC80054D8. Obviously as the pointer is now different, the returned data is [0, 0, 0, 0, 0 etc].
So:
If the the u8 buffer stays in the same place and is globally defined, why are my pointers to this buffer different depending on if I'm in lib.c or tb.c?
I'm creating my buffer in the header using:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
I'm creating my pointer in the lib.c file using:
u32 *RxBufferPtr_Data = RxBuffer_Data;
I'm creating my pointer in the tb.c file using:L
u32 *RxBufferPtr_Data = RxBuffer_Data; or &RxBuffer_Data. Both of these return the same value, and neither are equal to the pointer that correctly prints out the data of the buffer in the lib.c file.
static instructs the compiler to instantiate a variable with internal linkage to the current translation unit (.c file plus all #included stuff). Internal linkage means the symbol (name) is not exported. Thus, the fact that you use matching names is irrelevant.
So, here, you get a separate instance for each .c file that #includes that header. Being separate objects, they of course have different addresses.
If you want to share a single instance (and hence address) among multiple TUs, then just do the usual:
Declare the variable as extern in a header - not static. Doing so indicates that it has external linkage, i.e. is defined elsewhere. Do not define the variable in the header. It must be defined only once, so...
Define the variable in a single .c file only.
Some light reading on the basics of static vs extern will make this all clear.
Each compilation unit contains its own buffer because you declared it as having internal linkage by providing keyword static in the buffer declaration in the header.
You should declare it in the header like
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
and in some module define it like
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
or just like
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
without the initializer because in any case it will be initialized with zeroes by the compiler as having static storage duration.
In this case the buffer will be shared by all compilation units that include the header.
Here is the problem:
I'm creating my buffer in the header using:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
The above creates a separate copy of the variable in every c file from which the header is included. In other words, your would-be-globals from separate modules are invisible to the linker, which makes them unrelated to each other, and gives them separate addresses.
If you want to make a global variable, declare it in the header like this
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
then define it in the file containing your main() function like this:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
You define RxBuffer_Data to staticin your head file,it tell compiler you just use this variable in this file.When lib.c include your head file,it define in lib.c.And RxBuffer_Data will re-define in tb.c when include head file,this RxBuffer_Data is a new variable.So,you can find two pointer to RxBuffer_Data is different.
If you want to define global varibal,you can define it in lib.c:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
and declare in your head file:
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
By the way,do not define global varibles in head file,because once you include this head file,you will re-define it.
I wanted to know how could i make my code better by declaring the array 'data_pack[]' as a private .Im working in embedded field so i have limited RAM and Memory and all i wanted to do is two things.
1.I have a serial UI which gives me serial data of 50 Bytes and stores them directly to unsigned char data_pack[50]
2.And I wanted to access the array in another module to calculate and do other things.
Currently im keeping the array as global variable and can be accessed from any module in my project.If i wanted to keep data_pack[50] as private how can i access the array packets in another modules?
I hope i will be more clearer after explaining here:
I have four modules.
main.c
ui.c
display.c
display2.c
And If i wanted to keep data_pack[50] as pvt in ui.c and access it in other modules..how can i do it with out making it global.
For eg: In ui.c I would like the data_pack[] to get filled in and in
display.c and display2.c I want to access the array and read its
element.In that case how could i pass the array in to other source
files
What would be the best way to access data_pack[] by keeping it as private?
Or should i use structures instead?
You can make a global variable data_pack read-only in other compilation units by changing its forward reference to extern const .... For example, two files:
file1.c
char example[50] = {1, 2, 3};
void change() {
example[1] = 44;
}
file2.c
#include <stdio.h>
/* extern const char example[50]; array size not needed in extern declaration */
extern const char example[];
void change();
int main() {
printf("%d\n", example[1]); /* works */
change();
printf("%d\n", example[1]);
/* example[0] = 45; would cause a compile error */
return 0;
}
Therefore, file2.c will see example as an array of constant ints, meaning it can only be modified by file1.c. The code above would print 2, followed by 44.
However, you must be careful doing this. If the size of the array in the forward declaration differs from the actual size of the array in the compilation unit it is contained in, the compiler/linker will not tell you (at least it doesn't for me, using gcc -Wall -Wextra -ansi -pedantic). You can also leave the array size out of the extern declaration.
One thing to note is that the compiler may attempt to optimize the const value, as it may not expect the value to change, thus producing invalid optimizations. I've performed some tests, and GCC doesn't seem to do this, but as it is undefined behaviour you may wish to use a getter/setter solution instead.
I am dealing with the following issue in C. I use global variables for defining some global parameters in my code. I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file. In a nutshell, I am looking for a good way to "cast away" constness during variable initialization in C (I guess in C++ this would not be an issue thanks to const_cast)
I came up with a pattern based on macros to do so, as illustrated below.
It seems to work fine, but I have the following questions.
Does anyone see any hidden flaw or potential danger in the procedure below?
Would anyone discourage the following approach in favor of a simpler one?
My approach:
I have a main header file containing the definition of my global variable (int N) like so
/* main_header.h */
#ifdef global_params_reader
#define __TYPE__QUAL__
#else
#define __TYPE__QUAL__ const
#endif
__TYPE__QUAL__ int N;
I have a file "get_global_params.c" implementing the initialization of N, which sees N as "int N" (as it includes "main_header.h" after defining global_params_reader)
/* get_global_params.c */
#define global_params_reader
#include get_global_params.h
void get_global_params(char* filename){
N = ... ; // calling some function that reads the value of N from
// the datafile "filename" and returns it
}
and the corresponding header file "get_global_params.h"
/* get_global_params.h */
#include "main_header.h"
void get_global_params(char* filename);
Finally, I have a main.c, which sees N as "const int N" (as it includes "main_header.h" without defining global_params_reader):
/* main.c */
#include "main_header.h"
#include "get_global_params.h"
int main(int argc, char **argv){
// setting up input data file //
...
// initialize N //
get_global_params(datafile);
// do things with N //
...
}
I hope my explanation was clear enough.
Thanks for any feedback.
Just contain the globals in a separate file.
globl.h:
struct Globals{
int N;
//...
};
extern const struct Globals *const globals;
init_globl.h:
init_globals(/*Init Params*/);
globl.c
#include globl.h
#include init_globl.h
static struct Globals _globals;
const struct Globals *const globals = &_globals;
init_globals(/*Init Params*/){
// Initialize _globals;
//...
}
Now you can initialize the globals at startup by including init_globl.h in whatever file needs access to that functionality, everyone else can directly access the globals just by including globl.h, and using the notation globals->N.
If I were you, I would simply avoid this kind of global variables. Instead, I would define a struct with all those program parameters, and define one function that returns a const pointer to the one and only instance of this struct (singleton pattern). That way, the function that returns the pointer has non-const access to the singleton, while the entire rest of the program does not. This is precisely what you need, it's clean and object oriented, so there is no reason to mess around with macros and casts.
The instance can be declared as a static variable within the function or it can be malloc'ed to a static pointer. It does not really matter, because that is an implementation detail of that function which is never leaked to the outside. Nor does the rest of the code need to be aware of when the parameters are actually read, it just calls the function and it gets the one and only object with all valid parameters.
"I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file."
It is not possible to initialize a const in c during run-time. In c value either has or has not a const qualifier, and it is defined upon declaration. c does not support changing it. The semantics are fixed. But some expert with quoting the standard would be nicer and more ensuring.
I don't think this is possible in c++ either, but I won't bet on it, since c++ can do some magic here and there.
Here I have two files externdemo1.c and externdemo2.c.In the first file,I have declared and initialized a character array arr at file scope.But I have declared it in the second file externdemo2.c without the extern keyword and made use of it there in the function display(). Here are my confusions arising from it.Please answer these three:
//File No.1--externdemo1.c
#include<stdio.h>
#include "externdemo2.c"
extern int display();
char arr[3]={'3','4','7'};
//extern char arr[3]={'3','4','7'};
//extern int main()
int main()
{
printf("%d",display());
}
//File No.2--externdemo2.c
char arr[3];
int display()
{
return sizeof(arr);
}
1) Why does the program compile fine even though I have declared arr without the extern keyword in externdemo2.c?I had read that the default linkage of functions is external,but I am not sure if that's so even for variables.I only know that global variables have extern storage class.
2) What is the rigorous difference between extern storage class and extern linkage.I badly need a clarification about this.In the first file,where I have defined the array arr,I haven't used the keyword extern, but I know that it has extern storage class by default.But in the second file, isn't there any default extern ,storage class or linkage,about the global variable arr,ie, in externdemo2.c?
3) Check the commented out line in the first file externdemo1.c.Just to test it, I had used the line extern char arr[3]={'3','4','7'};.But it gives the error 'arr' initialized and declared 'extern'.What does this error mean? I have also mentioned a commented line extern int main(),but it works fine without error or warning.So why can we use extern for a function even though a function is extern by default,but not for a variable,like arr here?
Please take some time to bail me out over this.It will clear most of my lingering doubts about the whole extern thing.It will be immense help if you can answer all 3 bits 1),2) and 3). Especially 3) is eating my brains out
Main questions
Basically, because you've included the source of externdemo2.c in the file externdemo1.c.
This is the big question. Because there is no initializer, the line char arr[3]; in externdemo2.c generates a tentative definition of the array arr. When the actual definition with initialization is encountered, the tentative definition is no longer tentative — but neither is it a duplicate definition.
Regarding extern storage class vs extern linkage...Linkage refers to whether a symbol can be seen from outside the source file in which it is defined. A symbol with extern linkage can be accessed by name by other source files in which it is appropriately declared. To the extent it is defined, extern storage class means 'stored outside of the scope of a function', so independent of any function. The variable defined with exern storage class might or might not have extern linkage.
Because it is not defined with the keyword static, the array arr has extern linkage; it is a global variable.
With the commented out line uncommented out, you have two definitions of one array, which is not allowed.
I observe that you must be compiling just externdemo1.c to create a program — the compiler is including the code from externdemo2.c because it is directly included. You can create an object file from externdemo2.c. However, you cannot create a program by linking the object files from both externdemo1.c and externdemo2.c because that would lead to multiple definitions of the function display().
Auxilliary questions
I have placed both files in the [same directory]. If I don't include the second file in the first, then when I compile the first file it gives the error undefined reference to display. Since I have used extern for that function in the first file, isn't the linker supposed to link to it even if I don't include the second file? Or the linker looks for it only in default folders?
There are a couple of confusions here. Let's try dealing with them one at a time.
Linking
The linker (usually launched by the compiler) will link the object files and libraries that are specified on its command line. If you want two object files, call them externdemo1.obj and externdemo2.obj, linked together, you must tell the linker (via the build system in the IDE) that it needs to process both object files — as well as any libraries that it doesn't pick up by default. (The Standard C library, plus the platform-specific extensions, are normally picked up automatically, unless you go out of your way to stop that happening.)
The linker is not obliged to spend any time looking for stray object files that might satisfy references; indeed, it is expected to link only those object files and libraries that it is told to link and not add others at its whim. There are some caveats about libraries (the linker might add some libraries not mentioned on the command line if one of the libraries it is told to link with has references built into it to other libraries), but the linker doesn't add extra object files to the mix.
C++ with template instantiation might be argued to be a bit different, but it is actually following much the same rules.
Source code
You should have a header, externdemo.h, that contains:
#ifndef EXTERNDEMO_H_INCLUDED
#define EXTERNDEMO_H_INCLUDED
extern int display(void);
extern char arr[3]; // Or extern char arr[]; -- but NOT extern char *arr;
#endif /* EXTERNDEMO_H_INCLUDED */
You should then modify the source files to include the header:
//File No.1--externdemo1.c
#include <stdio.h>
#include "externdemo.h"
char arr[3] = { '3', '4', '7' };
int main(void)
{
printf("%d\n", display());
return 0;
}
and:
//File No.2--externdemo2.c
#include "externdemo.h"
int display(void)
{
return sizeof(arr);
}
The only tricky issue here is 'does externdemo2.c really know the size of arr?' The answer is 'Yes' (at least using GCC 4.7.1 on Mac OS X 10.8.3). However, if the extern declaration in the header did not include the size (extern char arr[];), you would get compilation errors such as:
externdemo2.c: In function ‘display’:
externdemo2.c:7:18: error: invalid application of ‘sizeof’ to incomplete type ‘char[]’
externdemo2.c:8:1: warning: control reaches end of non-void function [-Wreturn-type]
Your program looks a bit err. To me the #include "externdemo2.c" line appears invalid.
Following is the correction I have made and it works.
//File No.1--externdemo1.c
#include <stdio.h>
extern char arr[3];
extern int display();
int main()
{
printf("%d", arr[0]);
printf("%d",display());
}
//File No.2--externdemo2.c
char arr[3]={'3','4','7'};
int display()
{
return sizeof(arr);
}
Please follow the below links for better understanding:
Effects of the extern keyword on C functions
How do I use extern to share variables between source files?
Using #include as shown will make both as one file only. You can check the intermediate file with flag -E, as in:
gcc -E externdemo1.c
I am a beginner to C programming and I'm trying out different methods and experimenting with small programs.
I have four files. two header files and two source files. I want to:
Declare a variable (Actually two variables and a char) and a
function (from the second source file) in one header file.
Define these variables and assign values to them in a second header
file(variables from point 1).
Write a function including these two header files and using the
values from these files(point 2) in one source file (without a main-
just a function definition using the variables).
Have a main source file that invokes the function from the second
source file (from point 3.)
How do I come about this? I have included both header files in both the .c files. But when I try to compile and link it (using GCC in Linux) I get a
multiple definition ... first defined here error for all the variables.
I have looked at these answers First and Second
I didn't quite understand the answers in the Second as I'm not able to figure out how to use header guards.
I am not able to figure out how to check all of the boxes (points one through 4).
header1.h
extern int i,j; extern char c;
void ad_d();
header2.h
int j=6;int i=7;
char c='x';
fnfile.c
#include "header1.h"
#include "header2.h"
#include<stdio.h>
void ad_d()
{
i+=j;
printf("\n %d \t %c \n", i,c);
}
filemain.c
#include<stdio.h>
#include "header1.h"
#include "header2.h"
void main()
{
ad_d();
}
You can only define a variable once, that allcoates space in memory where the value will be stored. you can then declare the variable in each file (or better yet in a common header file) which will tell the compiler that a varialble of that name and type will be defined in one of the compiled files, and can be found at a later stage.
in the file where you want to define the variable use:
int my_global = 0; /* always good practice to initalize */
in other files (or a common header) use:
extern int my_global;
Now you can read or write my_global from any file where it is declared.
The header guard stuff is an attempt to move the definition and declaration into the same statement, at your level it is probably best that you get a handle on declaration vs definition before trying to play games like that.
int j=6;int i=7;
char c='x';
You don't want these in a header file, as they're definitions. Put them in the C file instead, and just include the same header in both files (with the extern declarations of the variables).
As it stands, both of your source files are trying to define these variables, which is why you get the error.