In C, when defining an array I can do the following:
int arr[] = {5, 2, 9, 8};
And thus I defined it and filled it up, but how do I define it in my .h file, and then fill it in my .c?
Like do something like
int arr[];
arr = {5, 2, 9, 8};
I'm pretty new to C, not sure how it would look
any suggestions?
Normally, you'd put:
extern int arr[];
In the .h file, and:
int arr[] = { 5, 2, 9, 8};
In the .c file.
Edit: Dale Hagglund and KevinDTimm raise good points: you only want to put the initialization in one .c file, and you only need to put anything in the .h file if you're going to access arr from code in more than one .c file.
You can use include guards to prevent the assignemnt from happening multiple times, but putting the assignment into headers is a very bad practice in my opinion. Put the intialization in a c file, in an init function instead and extern the array in the h file.
Related
I have a c program that comes below:
int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int C[size][size];
int multiplication()
{
//using array A, B and C here
return 0;
}
I also wrote a startup file by myself and compile them using risc-v compiler by the following command:
riscv64-unknown-elf-gcc -ffreestanding -march=rv32im -mabi=ilp32 -nostartfiles -nodefaultlibs -mno-relax crt0.s Myprogram.c -o Myprogram
Then using riscv64-unknown-elf-objdump -t Myprogram I can see that arrays A and B are in .data segment and array C is in .bss segment that makes sense.
But when I change my code such that I declared arrays A and B as local arrays to the function:
int C[size][size];
int multiplication()
{
int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
//using array A, B and C here
return 0;
}
I got the compilation error: undefined reference to `memcpy'.
It seems that it uses memcpy for allocating memory to the arrays while it's not the case when I declared the arrays as global.
Does anybody know why and what's the difference?
Large constants needed by a program are stored in the program's text segment, and copied where needed. When the compiler chooses to initialize a large variable by copying the initializer from the text segment, it generates a call to memcpy. There are other ways to compile this code, sure, but calling memcpy is perfectly sensible and efficient.
This doesn't happen for a global variable because they are initialized from the program's data segment. Since they only need to be initialized when the program starts, the same memory that contains the initializer when the program starts is then used for the variable.
You might think of main as a special function and of its local variables as essentially global variables, but they aren't. main is a function, and it can be called recursively. The compiler could in theory detect that some programs doesn't call main recursively and give it special treatment, but in practice, it doesn't, and it sure can't when it's linking some assembly code which could be finding its way to main.
Normally you don't see this because the standard library provides memcpy. But since you're using -nodefaultlibs, you need to supply an alternative implementation of memcmp, memset, memcpy and memmove, per the GCC documentation:
Most of the compiler support routines used by GCC are present in libgcc, but there are a few exceptions. GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp.
GCC & clang require freestanding environments to provide
memcpy, memmove, memset and memcmp. The GCC documentation says:
Most of the compiler support routines used by GCC are present in libgcc, but there are a few exceptions. GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp.
You need to implement them yourself it you do not want use the standard ones
You should also remember that there are more functions which can be required - for example, integer divisions and similar.
You can also see if your compiler provides libgcc or you can take the function you require from here (or or your port libgcc repo): https://github.com/gcc-mirror/gcc/tree/master/libgcc
I need to evaluate function with list of arguments from array of arguments as in this example:
int compute(...) {
int n;
va_list params;
va_start(params, n);
// some custom computation with no "va" output
va_end(params);
}
And some array of int (which is dynamic array, don't rely on fixed size):
int arr[10] = {0, 1, 3, 7, 8, 1, 3, 5, 7, 9};
And I need to call compute like JS function compute.apply(this, arr)
I'm implementing some library with C that's why I need it.
In C++ this is std::apply but I want the same in C.
Thanks
In C++ this is std::apply but I want the same in C.
Since you want the same in C, you'll surely accept that you have to fulfill the same requirements, in particular, as a tuple supports std::get and std::tuple_size, their C equivalents. Now, as long as the arguments from the array are accessed in order from first to last, std::get can be implemented with va_…(), but just as the stdarg variable argument lists need some means of determining the amount of arguments (like a format string or an argument count), std::tuple_size cannot be implemented without such a means. You won't do without passing this information.
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
I was taking a look at the Quake 1 GPL Code and I came across various similar header files, the purpose or use of which I don't seem to understand. They look like tables of some sorts and are structured like this
{1, 0},
{1, -1},
{1, -2},
{1, -3},
{1, -4},
{1, -5},[...]
Without anything before or after them. I understand they define something but I've never come across this kind of notation in C.
You can read one of the header files I'm referring to here.
My question is: what are those...things? The ASM is actually giving me less problems than that stuff.
These are probably multi-use includes. They can be used like so:
struct {int y; int y;} points[] = {
#include <points.inl>
};
The contents of a header do not have to be valid C; the C preprocessor will insert them wherever the #include directive is found, such as in the middle of a struct initialization in another source file. As long as it's valid C by the time it actually gets to the compiler, that's all that matters.
They can be used to initialize arrays.
You could use them like this:
int array[N][2] =
#include <header_file>
;
Suppose I want to share a global array of data across my program, for example:
int lookup_indexes[] = { -1, 1, 1, -1, 2, 1, 1, -2, 2, 2, -1, 1, 1, 2 };
What is the correct extern declaration for this array in the C header file?
Also what about an array like this:
int double_indexes[][5] = { { -1, 1, 1, -1, 1 }, { 2, -2, 2, 1, -1 } };
In my header file I tried this:
extern int lookup_indexes[];
extern int double_indexes[][5];
But this results in compiler errors:
water.h:5: error: array type has incomplete element type
I can't figure it out.
Thanks, Boda Cydo.
This link discusses the problems with arrays and sizes used as extern and how to manage them.
Declare a companion variable, containing the size of the array, defined and initialized (with sizeof) in the same source file where the array is defined
define a manifest constant for the size so that it can be used consistently in the definition and the extern declaration
Use some sentinel value (typically 0, -1, or NULL) in the array's last element, so that code can determine the end without an explicit size indication
The code you posted looks fine to me and compiles (gcc -std=c99 -pedantic and gcc -std=c90 -pedantic) on my machine. Have you copy-pasted these lines or could you have made a typo in your real header?
Example typos that could cause your error (pure guesswork):
extern int double_indexes[][]; /* forgot the 5 */
extern int double_indexes[5][]; /* [] and [5] swapped */