Determine positions in array at compile-time in c - c

Is there a way to determine a position within a const array at compile-time in c? Here's an example of what I'm trying to do:
const unsigned char DATA[] = {
// Part 1
// hundreds or thousands of values
// Part 2
// compiler records this position in the array in PART2
// hundreds or thousands of values
// Part 3
// compiler records this position in the array in PART3
// hundreds or thousands of values
// ...
};
const unsigned int PART_IDX [] = {
// index to Part 1
0,
// index to Part 2
PART2,
// index to Part 3
PART3,
// ...
};
I could calculate the indexes at run-time, but would rather have them already done, since the array is constant. I could make a program that analyzes the source code, counts the number of elements in each part, and inserts the data in PART_IDX, but I would really like to have the compiler do this at compile-time. That way if data gets inserted or deleted, or parts get added or removed, the compiler still generates correct code. Does someone know how I could do this? Thanks!
Edit:
To clarify, using a example with actual data:
const unsigned char DATA[] = {
// Part 1
0, 1, 2, 3, 4,
// Part 2
// compiler records this position in the array in PART2 (should be 5)
10, 11, 12, 13, 14, 15, 16,
// Part 3
// compiler records this position in the array in PART3 (should be 12)
20, 21, 22
};
const unsigned int PART_IDX [] = {
// index to Part 1
0,
// index to Part 2
PART2, // should be 5, points to 10 in the array
// index to Part 3
PART3, // should be 12, points to 20 in the array
};
Question is, what can I put in place of the lines that start with // compiler records this position ... to get the compiler to record the appropriate values in PART2 and PART3?

Rather than trying to kludge C to do something it was not meant to do, a better and common method is to prepare data for a C program by writing a program that prepares the data. That is, write some other program that counts the data in the parts and writes the C code necessary to initialize both DATA and PART_IDX.
Another option is:
Put all the data each part in a separate “.h” file, such as files “part1.h”, “part2.h”, “part3.h”.
To initialize DATA, include all of those header files in its initializer list.
To calculate the indices for the parts, use sizeof to calculate the numbers of elements in proxy arrays containing the preceding parts.
Example:
“part1.h” contains 10, 11, 12,.
“part2.h“ contains 20, 21,.
“part3.h” contains 30, 31, 32, 33,.
The C file is:
const unsigned char DATA[] =
{
#include "part1.h"
#include "part2.h"
#include "part3.h"
};
const unsigned int PART_IDX [] =
{
0,
sizeof (const unsigned char []) {
#include "part1.h"
} / sizeof (const unsigned char),
sizeof (const unsigned char []) {
#include "part1.h"
#include "part2.h"
} / sizeof (const unsigned char),
};
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 3; ++i)
printf("Part %d begins at index %d with value %d.\n",
i, PART_IDX[i], DATA[PART_IDX[i]]);
}

Is there a way to determine a position within a const array at compile-time in c?
Yes. Remember that C source files can be generated, and improve your build automation accordingly (e.g. edit your Makefile).
So just generate the second part (e.g. with some awk or Guile script on Linux, or your own simple meta-program coded in C -or some scripting language- that output portions of generated C code). Play with preprocessor tricks. See this answer for inspiration.
You could, assuming you use GCC as your C compiler, also consider writing your ad-hoc GCC plugin, but in your particular case it is not worth the effort.
BTW, my Bismon program uses such meta-programming tricks. And GCC itself has dozens of ad-hoc code generators.
If you generate some complex enough C code, I recommend keeping internally some kind of AST of it.

Related

C11: how to quickly convert a char array into ints, then modify ints and update char array

There are two parts of the problem that I don't know how to solve:
Input
The user can enter some inputs like 12,14y or 15m and I need to extract the two ints and the character. For now, I simply use:
char buffer[50];
scanf("%s", buffer);
switch (buffer[strlen(buffer)-1]) {
// ... I use this to read the last char
}
This can give me the information of how many ints I have to read:
one in the m,n case -> sscanf(buffer, "%d%c", int1, c)
two in the y,s,b case -> sscanf(buffer, "%d,%d%c", int1, int2, c)
I need these numbers for the core of my program, so I need int values not only the string.
The problem is that online I read about sscanf inefficiency and I need a good way to do this task quickly.
Output
My code has to modify these numbers just in one case (y) and conserve a modified copy of the user input. For example, users input is 1,12y then I have to modify it in 1,10y and store it as a char array so it's not only an input. The modification of int2 it's quite long to explain, I can say that the new value would be less than the original one (in my example from 12 I get 10). The only idea I have about this it's how to create the new char array: I can calculate int1 and int2 length trying to divide them with increasing power of 10 until I get a result between 1 and 9. e.g.:
int1 = 201:
201 no
20.1 no
2.01 yes
=> 3 tries, length = 3
Then I use a malloc. But then, how can I write my "output" in the new char array? e.g.:
input = "1,201y"
-> int1 = 1, int2 = 201
-> lenght(int1) = 1, length(int2) = 2
// if the core program sets int2 = 51, then
char *out = malloc(1+2+1):
// now I have to write "1,51y" in this char array
I've coded the "core" program already, but now I'd want to improve a fast "translation" of user input (because in the core program I need to know if it's a int1m or int1n or int1,int2y or int1,int2s or int1,int2b command) and I don't know how to modify user input to save it in a string (for strings I use char arrays dynamically allocated). Only the y command could modify int2.
I hope that it's clear what I've to done.
The problem is that online I read about sscanf inefficiency
"Online" isn't a very trustworthy source. Inefficiency depends entirely on what you compare the function with.
If you compare with any plain C function then all of the stdio.h functions are very much inefficient. As is malloc for that matter. However, printing to the screen and waiting on the human user are by far the largest bottlenecks in this program, so you might want to re-consider why and what you are optimizing.
That being said, you can easily roll out a manual specialized version of the string to integer conversion, by calling strtol family of functions. Here's a version supporting exactly 1 or 2 integers in the input string (it can easily be rewritten to use a loop instead):
#include <stdlib.h>
int parse_input (const char* input, int* i1, int* i2, char* ch)
{
char* endptr=NULL;
const char* cptr=input;
int result;
result = strtol(cptr, &endptr, 10);
if(cptr==endptr)
{
return 0;
}
*i1 = result;
if(*endptr != ',')
{
*ch = *endptr;
return 1;
}
cptr=endptr+1;
result = strtol(cptr, &endptr, 10);
if(cptr==endptr)
{
return 0;
}
*i2 = result;
*ch = *endptr;
return 2;
}
Some extra error handling might be needed too. This gives around 50 instructions when compiled for x86_64, not counting strtol calls. Where some 20 of those instructions are related to the parameter stacking and calling convention.

SHA256 digest differs between array initializer and string

I use the sha256 function of Microchip ATECC508A security chip. My code looks like this:
int main(void) {
uint8_t message[32] = {0}; // Method 1
//uint8_t message[32] = "00000000000000000000000000000000"; // Method 2
foobar(message, sizeof(message));
}
void foobar(uint8_t *message, int length) {
uint8_t digest[32];
sha256(message, length, digest);
// printf statements for calculated hashes ...
}
Method 1: 66687AADF862BD776C8FC18B8E9F8E20089714856EE233B3902A591D0D5F2925
Method 2: 84E0C0EAFAA95A34C293F278AC52E45CE537BAB5E752A00E6959A13AE103B65A
Method 2 delievers the corresponding hash I expect for 32 zeros, but when I use the static array initializer in method 1, the hash is wrong and I don't know why. I've checked the resulting sha256 hashes here.
I would appreciate any help, thank you very much.
EDIT:
I was able to to initialize the whole array with characters of zeros with:
uint8_t message[32] = { [0 ... 31] = '0'}.
This only works on gcc compilers.
In the second case, the array is not filled with the number 0 but is filled with the character '0'.
In ASCII, the encoding for '0' is 48, so assuming your system uses ASCII then every element of your array has the value 48.

C/CAPL defining one array from another

this is my first question here, please notice I'm very new to coding. Quick search doesn't helped me since I think the answer might be too simple.
Im writing some code in CAPL (a CANoe specific language based on C).
Lets have my scenario simplified: I have to read 10 values Input, but I'm just able to read one by a time (due to HW reasons).
My value is stored in a buffer (rsBuf), now I'm trying to define a help-array for everytime I read the value (rsBuf1 ... 10).
At the end I will create another array with added values of rsBuf1 ... rsBuf10.
for every "read-action", I want to define
rsBuf1 = rsBuf;
rsBuf2 = rsBuf; and so on...
error: for "rsBuf1 = rsBuf;" Error 1112 at (732,16): operand types are incompatible.
Compilation failed -- 1 errors, 0 warnings
my "real" values:
variables
{
byte rsBuf[1024];
byte rsBuf1[1024];
}
is there an easy way to do this one-array-from-another?
I also tried some other notations I found, like rsBuf1 = {rsBuf}, but wasn't helping. Of course I could define
rsBuf1[1]=rsBuf[1];
...
rsBuf1[1024]=rsBuf[1024];
but that would be a waste of time I guess.
Thanks in advance, cheers Robert
You can't copy arrays through assignment in C, because the syntax does not allow it. The best solution is to use the memcpy function.
Alternatively, if it makes sense for the program design, you could put the arrays inside a wrapper struct:
typedef struct
{
int array [5];
} array_wrapper_t;
array_wrapper_t this = {1,2,3,4,5};
array_wrapper_t that;
that = this;
This should yield identical machine code as a call to memcpy.
Option 1
You can use memcpy as follows to copy the entire array:
memcpy(rsBuf1, rsBuf, elcount(rsBuf));
The following would copy the first four bytes:
memcpy(rsBuf1, rsBuf, 4);
Option 2
Optionally you could define your copy-function, see the copy_buffer() implementation:
variables
{
byte rsBuf[1024] = {1, 2, 3, 4, 5, 6, 7, 8};
byte rsBuf1[1024];
}
on start
{
print_buffer(rsBuf, 8);
print_buffer(rsBuf1, 8);
copy_buffer(rsBuf1, rsBuf, elcount(rsBuf));
print_buffer(rsBuf1, 8);
}
void copy_buffer(byte dest[], byte src[], long len)
{
int i;
for (i = 0; i < len; i++)
dest[i] = src[i];
}
void print_buffer(byte buf[], byte len)
{
int i;
writeLineEx(0, 0, ">");
for (i = 0; i < len; i++)
writeEx(0, 0, " 0x%02x", buf[i]);
}

Can I use labels as index in C global data table?

I have a large global array in which I keep changing some of the values which when compiled for different purposes requires the table to be altered. Basically the table as a core structure and based on different purposes additional values may get added/removed from it.
The values are somewhat like:
int global_array[] =
{
...
6, 6, 78, 9,
12,
13,5
19,
47, 768, 98, 89
...
};
I need to access some of core structure values (lets say "12" here) inside these table. So while compiling for different purposes, index of concerned value ("12") changes. For same reason I cannot keep this table as structure. Keep in mind this is a huge table and for some reason we don't write values in uniform fashion (read linear).
So for every new purpose I have to manually count index of value "12" which is tedious. I want a future proof process.
I was wondering if I could use something like:
int global_array[] =
{
...
6, 6, 78, 9,
INDEX: 12,
13,5
19,
47, 768, 98, 89
...
};
And access/modify values at run-time as below:
*(uint8 *)INDEX = 20;
You can keep additional pointer variables around that point to specific entries. Whenever needed, you can adjust the array entry the pointer points to.
Example:
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
int *idx = &global[0];
int main() {
*idx = 20;
printf("%d\n", *idx);
return 0;
}
Alternatively, you could use a preprocessor macro (if the location that is referred to is known at compile time and will not change):
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
#define INDEX (global[0])
int main() {
INDEX = 20;
printf("%d\n", INDEX);
return 0;
}
Given you only need to do this once at program start, maybe you just need a function that does the counting for you.
Example:
#include <stdio.h>
int global[] = {1,2,3,4,5,6,7};
int find_index(int value, int *array, size_t size) {
for (int i = 0; i < size; i++)
if (array[i] == value)
return i;
return -1;
}
int main() {
int value = 4;
int index = find_index(value, global, sizeof(global)/sizeof(*global));
printf("index of %d: %d\n", value, index);
return 0;
}
Here's the output:
$ gcc tt.c -std=c99 && ./a.out
index of 4: 3
If the positions of lots of entries needs to be tracked throughout the entire runtime of the application you should consider using a key-value storage (e.g., a binary search tree) to keep track of the values' indices. You should then use special methods that encapsulate the update and retrieval operations that will also adjust the indices stored in that "index" data structure.
From ISO/IEC9899:
6.8.6.1 The goto statement
Constraints
1 The identifier in a goto statement shall name a label located somewhere in the enclosing function.
A goto statement shall not jump from outside the scope of an identifier having
a variably modified type to inside the scope of that identifier.
As a global aray is not located in an enclosed function, this is not allowed!
C does not provide any syntax to do what you want.
One way to solve this so you don't have to count something with each change, is to have a tool of yours do the counting. After all, machines are good at counting things. For example, you could mark the interesting postitions in the initializer with a special comment, i.e.
int global_array[] =
{
6, 6, 78, 9,
12, /* INDEX12 */
13,5,
19,
47, 768, 98, 89
...
};
The index for the array element is then found by counting the commas from the start of the declaration, minus one. Turn the result into a compile-time macro with -DINDEX12=42, et voilà! All you need is an idea of where the declaration starts (putting it in a separate header file is the easy route), and run for example
$ awk '/global_array/,/INDEX12/ { commas += gsub(/,/, ",") }
END {print "-DINDEX12=" commas - 1}' file.h
-DINDEX12=4
This is easily extended to deal with any number of INDEXNNN macros. Beware of the potential off-by-one for the last array initializer (which doesn't have a comma in your snippet, but C does allow it...)
Placing this preprocessing in a snugly Makefile left as an exercise.

Proper way to count number of string elements in an array in C

This is the code I'm blundering around with.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i=0;
for(i=1;i<argc;i++){
printf("arg %i: %s\n", i , argv[i]);
}
//custom array of strings
char *states[] = {
"California", "Oregon", "Idaho", "Arkansas", "Washington",
"Texas", "Montana"
};
int num_states = sizeof(*states)-1;
printf("%i\n", num_states);
for(i=0;i<num_states;i++){
printf("state %i: %s\n", i, states[i]);
}
return 0;
}
My question is a fairly simple one, before I got this work I was encountering a very frustrating segfault.
"int num_states = sizeof(*states)-1;" this line works to return the number of string in array, minus one (not sure why the -1 is required to prevent segfault)
"int num_states = sizeof(states);" this returned 56, and caused my for loop to iterate through stuff that didn't exist.
The problem is I'm not sure what the difference is. My best guess is that the first line counts the total number of bytes that states[] is composed of, and that the second counts the number of locations in memory stored by *states.
Please correct me if my thinking is wrong. And if you can tell me why the -1 somehow prevented this segfault I'd appreciate it.
The right way to do it
The value in num_states should be:
int num_states = sizeof(states) / sizeof(states[0]);
That is, the number of elements in an array is the size of the array divided by the size of the zeroth element of the array (which is the same size as every other element of the array).
This can be generalized to handle other arrays. Harking back to Fortran and/or Basic, I often use a macro:
#define DIM(x) (sizeof(x)/sizeof(*(x)))
Be careful: this only works with arrays where the size is known. It does not work with 'arrays' passed to functions; such 'arrays' degenerate to pointers, and you end up with a wrong answer. If you defined the function in the current source file (outside any function), or in the current function, you can use this safely.
Why your code worked
As to why your example worked — the answer is 'coincidence'. It depends on the facts that:
Your array has 7 elements.
The size of a pointer is 8 bytes on your system.
The value of sizeof(*states) is 8 because *states is a char * and (on your 64-bit machine), the size of a pointer is 8. Therefore int num_states = sizeof(*states)-1; 'works' by coincidence. If you added or removed any entries from the array, or compiled the code on a 32-bit machine, then it would fail again (the exact modes of failure depending on the change in the environment), whereas computing the number of elements as shown would work correctly regardless of any of those changes.

Resources