Using array in .h file - c

I am trying to learn to program in C (not C++!). I've read about external variables, which should (according to the writer) give a nicer code. In order to use the external variables, I must #define them in the .h file, before I can use them in main.c file, using the extern command in front of the variable. I am trying to create an array in the .h file like this:
#define timeVals[4][2];
timeVals[0][0] = 7;
timeVals[0][1] = 45;
timeVals[1][0] = 8;
timeVals[1][1] = 15;
timeVals[2][0] = 9;
timeVals[2][1] = 30;
timeVals[3][0] = 10;
timeVals[3][1] = 25;
(it's a clock I'm trying to make, simple program in console). The first column indicates hours and the second indicates minutes. In my main I have written
extern int timeVals[][];
but I get an error telling me that " expected identifier or '(' before '[' token|" and I can't see what the issue is... any ideas or advices?
I am using the .h file to learn how to use external variables, so I can't move the values back into main.c

First, this:
#define timeVals[4][2];
Is a confusion. You mean this:
int timeVals[4][2];
Put that in your .h file, then in your .c file, something like this:
int timeVals[4][2] = {
{ 1, 2 }, // ...
};
That's how you initialize the entire array (any unspecified elements will be zero).

Related

Initialize an array in C

Since it's not possible to assign values to a const after it's initialized, how can I achieve this?
const double input1[1000][2];
for(int i = 0; i < 1000; i++){
input1[i][0] = i;
input1[i][1] = i*2;
}
You'll have to generate the explicit initialization (i.e. the { {0, 0}, {1, 2}, {2, 4}, ... etc etc ... {1000, 2000} }.
You can do this with map/apply macros, or with your build system - having it run some script which generates that initialization sequence and plants it into the file.
You mentioned in the comments that this data is a training session data for a neural network.
I assume that you don't want to input 2000 values by hand and I assume that these values
come from another file, perhaps a csv or the output of another program that
generates the training data.
In that case, I'd write a script that generates a header file from the training
data that looks like this:
// training_data.h
// trainng data, automatically generated by script gen_training_data.py
// do not modify this file
#ifndef TRAINING_DATA_H
#define TRAINING_DATA_H
const double traing_data[1000][2] = {
{ 0, 1 },
{ 0, 2 },
....
};
#endif
The script (that you can write with other languages, bash, python, perl) would
take the training data and generate the header file for you, so you don't have
to write 2000 values by hand. Then you can use it in your C program like this:
#include <stdio.h>
#include "training_data.h" // include auto generated file
int main(void)
{
...
feed_to_neural_network(training_data);
...
}
If you use a build system like cmake, you can let cmake execute your script so
that it autogenerates the header file before compiling. That would save you on
the long run a lot of time.
I don't understand why would you want to store the index value in the first index. But removing const can solve your issue. But better thing to do would be, to just store the value instead of index. Like following:
double input1[1000];
for (int i = 0; i < 1000; i++)
{
input1[i] = i * 2;
}

C : Including a source file instead of a header

I am a beginner in library linking and have spent two days trying to link the libcrypto library to my C program on Visual Studio 2017.
I have had to include applink.c to solve my issues. But I think it is very weird to include something which is not a header. After searching a bit on the internet, I learnt that including a source file is something that exist but that one should avoid doing. Why then the openssl library does not ?
I don't think it is particularly relevant, but here is a small overview of this source file, you can find the whole source file here.
#define APPLINK_OPEN 18 /* formally can't be used, as flags can vary */
#define APPLINK_READ 19
#define APPLINK_WRITE 20
#define APPLINK_LSEEK 21
#define APPLINK_CLOSE 22
#define APPLINK_MAX 22 /* always same as last macro */
#ifndef APPMACROS_ONLY
# include <stdio.h>
# include <io.h>
# include <fcntl.h>
static void *app_stdin(void)
{
return stdin;
}
static void *app_stdout(void)
{
return stdout;
}
if (once) {
OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin;
OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout;
OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr;
OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf;
OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets;
OPENSSL_ApplinkTable[APPLINK_FREAD] = fread;
OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite;
OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod;
OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof;
OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose;
OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen;
OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek;
OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell;
OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush;
OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror;
OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr;
OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno;
OPENSSL_ApplinkTable[APPLINK_OPEN] = _open;
OPENSSL_ApplinkTable[APPLINK_READ] = _read;
OPENSSL_ApplinkTable[APPLINK_WRITE] = _write;
OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek;
OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close;
once = 0;
}
What is the difference between including a header and a source file ? What are the cons and pros to do that ?
This post isn't asking for a way to fix the link problems
Including a file is just like copying the file into your C file.
This means that anything that includes the C file will have its own sort of copy of the functions in applink.c.
You'll also notice that they're declared 'static', meaning that these copies are local to their respective files, and cannot create conflicts. They'll likely be inlined, even.
In general, this is a trade-off between binary size and compile time on one hand, and runtime speed and code simplicity on the other.
This isn't a rare thing to see, what surprises me more is that it's .c and not .h.

C append to an array in header file

I have multiple header files, each of them must append a number to an array to register it's functions.
Currently I have a function with a unique name in each header file, and in the program file I need to call all those functions in one combining function.
int register1() { return 100; }; //in header1.h
int register2() { return 200; }; //in header2.h
int register3() { return 300; }; //in header3.h
int register4() { return 400; }; //in header4.h
int registered[] = {register1(),register2(),register3(),register4()}; //main.c
But this is quite inconvenient because I need to modify in two places when I add or remove header files. Better would be to modify the header file only. I was thinking about a preprocessor define, so in each header I can just use something like:
#define Registered Registered,100 // header1.h
#define Registered Registered,200 // header2.h
int registered[] = {Registered}; // main.c
But this of course will not compile, because new define redefines the old one. So is there a way to append a define? Or other way to append a number to an array without modifying two files?
This is C, not C++, otherwise I would use a class instance with constructor that would just write to an array. Somethink like that:
struct __header1{ __header1() {
global_array[global_array_ptr++] = 100;
} } __header1_inst;
and then convert it to a nice macro:
#define register(hdr, func) struct __header##hdr{ __header##hdr() { \
global_array[global_array_ptr++] = func; \
} } __header##hdr##_inst;
register(1, 100) // header1.h
register(2, 200) // header2.h
IMHO, this is a hack and I would advise against it. Even if you could do that in C, consider situation where one such header file is included by several modules. There will be an identical entry in the global array for every such module. Next, even though you can do it in C++, the order of global object initialization is undefined there, so initialization of another global object relying on contents of the global array will be unreliable.
Additionally, this is a really complicated way to do a simple thing, and obscures the meaning considerably. Apart from the array-filling code itself being complex, tracking includes will become burdensome when dependencies get beyond trivial. So, just fill that global array in a specific place explicitly.

C programming error - counter already defined?

ERRORS:
1) _counter already defined error
2) one or more multiply defined symbols found
structure.h:
extern int counter = 0;
List.c:
in one method i increment the counter.
++counter;
in another method i set the counter to a value within an object
llist->taskID = counter;
Messages.c:
use counter for while loop
while(counter < 1)
{
//do stuff
}
why does this error occur? I did a ctrl F and searched for all the instances i use counter... these are the only instances i use it...
Your header file structure.h should only have a declaration (not a definition), like:
extern int counter;
One (only) of the implementation files, conventionally the *.c file containing main, should have a definition like
int counter = 0;

How does cryoPID create ELF headers or is there an easy way for ELF generation?

I'm trying to do a checkpoint/restart program in C and I'm studying cryoPID's code to see how a process can be restarted. In it's code, cryoPID creates the ELF header of the process to be restarted in a function that uses some global variable and it's really confusing.
I have been searching for an easy way to create an ELF executable file, even trying out libelf, but I find that most of the times some necessary information is vague in the documentation of these programs and I cannot get to understand how to do it. So any help in that matter would be great.
Seeing cryoPID's code I see that it does the whole creation in an easy way, not having to set all header fields, etc. But I cannot seem to understand the code that it uses.
First of all, in the function that creates the ELF the following code is relevant (it's in arch-x86_64/elfwriter.c):
Elf64_Ehdr *e;
Elf64_Shdr *s;
Elf64_Phdr *p;
char* strtab;
int i, j;
int got_it;
unsigned long cur_brk = 0;
e = (Elf64_Ehdr*)stub_start;
assert(e->e_shoff != 0);
assert(e->e_shentsize == sizeof(Elf64_Shdr));
assert(e->e_shstrndx != SHN_UNDEF);
s = (Elf64_Shdr*)(stub_start+(e->e_shoff+(e->e_shstrndx*e->e_shentsize)));
strtab = stub_start+s->sh_offset;
stub_start is a global variable defined with the macro declare_writer in cryopid.h:
#define declare_writer(s, x, desc) \
extern char *_binary_stub_##s##_start; \
extern int _binary_stub_##s##_size; \
struct stream_ops *stream_ops = &x; \
char *stub_start = (char*)&_binary_stub_##s##_start; \
long stub_size = (long)&_binary_stub_##s##_size
This macro is used in writer_*.c which are the files that implement writers for files. For example in writer_buffered.c, the macro is called with this code:
struct stream_ops buf_ops = {
.init = buf_init,
.read = buf_read,
.write = buf_write,
.finish = buf_finish,
.ftell = buf_ftell,
.dup2 = buf_dup2,
};
declare_writer(buffered, buf_ops, "Writes an output file with buffering");
So stub_start gets declared as an uninitialized global variable (the code above is not in any function) and seeing that all the variables in declare_writer are not set in any other part of the code, I assume that stub_start just point to some part of the .bss section, but it seems like cryoPID use it like it's pointing to its own ELF header.
Can anyone help me with this problem or assist me in anyway to create ELF headers easily?
As mentioned in the comment, it uses something similar to objcopy to set those variables (it doesn't use the objcopy command, but custom linkers that I think could be the ones that area "setting" the variables). Couldn't exactly find what, but I could reproduce the behavior by mmap'ing an executable file previously compiled and setting the variables stub_start and stub_size with that map.

Resources