I want to create a large number of declarations of static arrays, each with a different (static) size. I also want to be able to create an instance of all of them, and access them easily just with their ID. Can this be done with macros in C ?
i.e. I want to shorten this code
int array_1[SIZE_1];
int array_2[SIZE_2];
int array_3[SIZE_3];
int array_4[SIZE_4];
int array_5[SIZE_5];
int array_6[SIZE_6];
.
.
.
int array_40[SIZE_40];
and create this code (where the parts between <> are the ones I hope macros can do for me).
int StoreInArray(int array_id, int position, int value)
{
if(position < SIZE_<array_id>)
{
array_<array_id>[position] = value;
return 0;
}
else
{
return 1;
}
}
Of note : memory imprint is important. I really want to have each array be exactly the size that it must be, and no more - unless a cheap solution is offered.
The correct solution is likely to reconsider your overall program design and instead do something like this:
typedef struct
{
int* data;
size_t size;
} array_t;
const array_t array [40] =
{
{ some_array, 3 },
{ some_other_array, 5 },
...
};
A much worse idea is to implement an evil macro. It might look like this:
// NOT RECOMMENDED
#define StoreInArray(id,pos,val) (pos < SIZE_##id ? (array_##id[pos] = val,1) : 0)
Where the parameter id is an integer constant such as 1. Token concatenation then forms SIZE_1, array_1 etc as the macro is expanded.
This is written as a function-like macro only assigning to the array if pos is smaller than the array size. If so, the macro returns 1 otherwise 0. The comma operator is used inside the conditional operator ?: to achieve this.
Example:
#include <stdio.h>
#define SIZE_1 4
#define SIZE_2 2
#define SIZE_3 5
int array_1[SIZE_1];
int array_2[SIZE_2];
int array_3[SIZE_3];
#define StoreInArray(id,pos,val) (pos < SIZE_##id ? (array_##id[pos] = val,1) : 0)
int main(void)
{
if(StoreInArray(1, 3, 123))
{
printf("%d\n", array_1[3]); // prints 123
}
if(StoreInArray(1, 4, 123))
{
printf("%d\n", array_1[3]); // doesn't get executed
}
if(StoreInArray(3, 4, 456))
{
printf("%d\n", array_3[4]); // prints 456
}
}
Related
I am working on an Eclipse IDE doing some embedded C programming and I am a bit stuck on how I should proceed. My incomplete code is below -
#define ARRAYSIZE 50
void pressure_data(int *var1, int var2)
{
var2 = ARRAYSIZE;
int i;
uint16_t pressure;
for (i = 0; i < var2; i++)
{
pressure = pressure_read();
var1++;
}
}
int main();
{
int array[ARRAYSIZE];
pressure_data(array, 50);
return 0;
}
I would like my 'main' to create a 1D array with a size 50 (defined by ARRAYSIZE)
Each element of this 1D would be populated by a uint16_t value 'pressure' which is assigned by a separate function called 'pressure_read();'
The loop in the 'pressure_data' function would capture a new value of 'pressure' which would then fill the next index of the 1D array in 'main' and so on until the array contains 50 different 'pressure' values
Currently, this code will capture 50 different values of 'pressure' and print them into the terminal on Eclipse but I have omitted those lines for simplicity's sake.
What is the best method of passing a result of a function 'pressure_data', into each index of an array in my main?
I am relative beginner when it comes to C but have been taking some time to learn and understand using pointers as I know they are often used in conjunction with arrays.
Any help would be greatly appreciated.
Since you already have size limit of fifty on your array, you might simplify things in your function calls. Following is one example of how you might perform your task.
#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE 50
typedef unsigned short uint16_t;
uint16_t pressure_read()
{
/* For now just return an integer */
return 15;
}
void pressure_data(uint16_t var1[])
{
for (int i = 0; i < ARRAYSIZE; i++)
{
var1[i] = pressure_read();
}
}
int main()
{
uint16_t array[ARRAYSIZE];
pressure_data(array);
for (int i = 0; i < ARRAYSIZE; i++)
{
printf("Pressure: %d\n", array[i]);
}
return 0;
}
Note that in the function, the reference to a one-dimensional array is made in lieu of an integer pointer. Both are quite valid. The usage of the "[]" designation is just a point of preference. But this allows for some simplification of the population of the array.
Give that a try and see if this fulfils the spirit of your project.
How to make a dynamic while loop program in C?
Because of this:
if {
while
} else if {
while
} else {
while
}
I want to make a program doing dynamic while loop. I did two approaches.
first: (not work)
#include <stdio.h>
#define aaa printf("0\n")
int main() {
int x = 1, i = 1;
if (x == 1) {
#undef aaa
#define aaa printf("1\n")
} else {
#undef aaa
#define aaa printf("2\n")
}
while (i <= 10) {
aaa;
i++;
}
return 0;
}
second: (works)
#include <stdio.h>
typedef void (*FunctionName)();
void fun1();
void fun2();
int main() {
int x = 1, i = 1;
FunctionName y;
y = (x == 1) ? fun1 : fun2;
while (i <= 10) {
y();
i++;
}
return 0;
}
void fun1() {
printf("1\n");
}
void fun2() {
printf("2\n");
}
but, it can only accept same type of functions. in this case, the y().
it can't accept two or more types of functions at the same time.
for example: f1(a) and f2(a,b).
so, I have to make all functions to same type because it can't accept diff types.
this dynamic while loop program can only accept one type of functions.
then it is not full dynamic.
how can I solve the problem? how can I make it accept all kinds of functions?
any comments are welcome. thanks.
I'm not sure what problem you're trying to solve, but you could sort of make it work by sending the arguments with a void pointer.
typedef void (*FunctionName)(void *);
Then (if you want several parameters) create different structs for different functions:
struct fooArgs {
int x;
double y;
char *s;
};
Then create a function like this:
void foo(void *args) {
struct fooArgs *a = (struct fooArgs*)args;
int x = a->x;
double y = a->y;
char *s = a->s;
/* Do stuff */
}
You need to write something similar to y = (x == 1) ? fun1 : fun2; for the arguments. It could look something like this:
void *args;
struct fooArgs a = { 5, 6.7, NULL };
if(x == 1) {
y = foo;
args = a;
} else if (x == 2) {
y = bar;
args = NULL; // For a function without arguments;
}
while (i <= 10) {
y(args);
i++;
}
However, I don't recommend doing this unless you are really sure about what you are doing. If it is for performance, the gain is likely very low, and it's even likely that you just make it difficult for the compiler optimizer with worse performance as a result. Use things like this for performance as an absolute last resort, and only if you really need those extra milliseconds.
put switch or if else for more complicated conditions inside the while loop:
while(i <= 10)
{
if(condition 1)
//call f1();
...
else if (condition n)
{
// call fn;
...
else
{
// nothing of the prevous cases
}
i ++
}
you can also use swithch case inside the while loop if you are comparing against constants...
hope it helps
but, it can only accept same type of functions. in this case, the y(). it can't accept two or more types of functions at the same time. for example: f1(a) and f2(a,b). so, I have to make all functions to same type because it can't accept diff types.
Yes, because otherwise, what would be the arguments? In other words your fun1 and fun2 take no parameters. If you want to call a fun3 that takes 1 parameter, what would be the argument?
In other words, consider:
void fun3(int);
y = fun3;
y(???);
For some values of y, you would have to pass different number of arguments. Same for the return type.
What you would have to do is to create a wrapper function that does what is called a partial application of e.g. fun3:
void g() {
fun3(42);
}
y = g;
y();
Here, g has the responsibility of knowing what the arguments of fun3 are (they may be constant as in this example, or come from somewhere else).
In languages that support user-defined types (and maybe OOP), like C++, a typical solution is to create a "Callable" object that stores the arguments as data members and can be called as if it was a function.
Further, in some of those languages, you get some syntax sugar to easily create those Callable objects in-place, typically called lambdas or closures.
I am a C newbie, I have stored few look up Tables in the header file that need to be used in my C program.
For example, I'm using
static int LookupTable[ROW_SIZE][COL_SIZE] = FIRST_TABLE;
static int LookupTable[ROW_SIZE][COL_SIZE] = SECOND_TABLE;
static int LookupTable[ROW_SIZE][COL_SIZE] = THIRD_TABLE;
static int LookupTable[ROW_SIZE][COL_SIZE] = FOURTH_TABLE;
I have defined macros for ROW_SIZE and COL_SIZE where the COL_SIZE is fixed and ROW_SIZE is variable.
#define COL_SIZE 2
#define ROW_SIZE 2 //<! 1 x input (where input = {2,3,4,5})
I need to use the lookup tables based on the input value. That is, use:
FIRST_TABLE when input is 2 (so ROW_SIZE = 1 x 2 )
SECOND_TABLE when input is 3 (so ROW_SIZE = 1 x 3)
THIRD_TABLE when input is 4 (so ROW_SIZE = 1 x 4)
FOURTH_TABLE when input is 5 (so ROW_SIZE = 1 x 5)
Currently, I'm manually updating the ROW_SIZE everytime based on the input value and using the respective lookuptable as shown below.
#include<stdio.h>
#define FIRST_TABLE \
{ \
{1,2},\
{3,4}\
}
#define SECOND_TABLE \
{ \
{1,2},\
{11,22},\
{3,4}\
}
#define THIRD_TABLE \
{ \
{1,2},\
{11,22},\
{21,31},\
{3,4}\
}
#define FOURTH_TABLE \
{ \
{1,2},\
{10,20},\
{30,40},\
{50,60},\
{3,4}\
}
#define ROW_SIZE 2 // 2->FIRST_TABLE, 3->SECOND_TABLE, 4-> THIRD_TABLE, 5->FOURTH_TABLE
#define COL_SIZE 2
int main()
{
static int LookupTable[ROW_SIZE][COL_SIZE] = FIRST_TABLE;
//static int LookupTable[ROW_SIZE][COL_SIZE] = SECOND_TABLE;
//static int LookupTable[ROW_SIZE][COL_SIZE] = THIRD_TABLE;
//static int LookupTable[ROW_SIZE][COL_SIZE] = FOURTH_TABLE;
int i,j;
for(i=0;i<ROW_SIZE;i++)
{
for(j=0;j<COL_SIZE;j++)
{
printf("%d\t",LookupTable[i][j]);
}
printf("\n");
}
return 0;
}
Could someone please advise me on how I could define the ROW_SIZE and select the lookuptable automatically when the input value is known. For example, if input = 2, it should automatically choose ROW_SIZE = 2 and select FIRST_TABLE.
Please note that 'input' value is an external parameter coming from different source file.
As is, both of your macros are only definable before run-time. i.e. at compile-time, the value that defines your macro is locked in.
For your macro to produce a variable value, change:
#define ROW_SIZE 250 //<! 25 x parameter (where parameter = {10,15,20,25,...,100})
To:
#define ROW_SIZE(x) 25*(x) //<! 25 x parameter (where parameter = {10,15,20,25,...,100})
Then in the calling code, x should be defined in scope of where the macro is called. In this example, x is created as an int [4] array with automatic scope. It could be a global, or passed as a function argument, as long as it is defined:
int i, x[4]={10,15,20,25};
for(i=0;i<4;i++)
{
//select and use lookup
LookupTable[ROW_SIZE(x[i])][COL_SIZE];// Each iteration is expanded to
// LookupTable[25*x[i]][COL_SIZE];
...
For more information, here is a C macros tutorial.
Edit to address request in comments:
A lookup table is simply an initialized array that contains
precalculated information. They are typically used to avoid performing
complex (and hence time consuming) calculations.
...and more on tables From A tutorial on lookup tables in C.
With that in mind, there is too much I do not know about how you intend to use your lookup tables, but given the description of your needs, which includes tables of differing sizes, and the need to access them dynamically, the following illustrates one method where instead of #defines, the collection of tables is created using arrays of static const int, (varying sizes) and a pointer to an array: int *[], where size == count of tables in collection, can be accessed simply by by normal array indexing.
The following is implemented as described above, and demonstrates a method that can be used to Auto select lookup tables based on input parameter.
// define in header file
//replaces your #define tables
static const int table1[1][2] = {1,2};
static const int table2[2][2] = {{1,2},{3,4}};
static const int table3[3][2] = {{1,2},{11,22},{3,4}};
static const int table4[4][2] = {{1,2},{11,22},{21,31},{3,4}};
static const int table5[5][2] = {{1,2},{10,20},{30,40},{50,60},{3,4}};
#define MAX_TABLES 5
//array of pointers to allow lookup table selection via array indexing.
//( static scope necessary if table is used in more than one .c file )
static int *table[MAX_TABLES] = {(int *)table1, (int *)table2, (int *)table3, (int *)table4, (int *)table5};
// end - define in header file
void access_table(int table);
int main(void)
{
int i;
for(i=0;i<MAX_TABLES;i++)
{
access_table(i);//select lookup tables based on input parameter ( i )
}
getchar();
return 0;
}
void access_table(int index) // view contents of the selected table
{
//by definition all tables have rows equal to table number and columns always == 2
int loops = 2*index+2;
int j;
for(j=0;j<loops;j++)
{
printf("%d ", table[index][j]);
}
printf("\n");
}
Produces the following output:
#define ID_A 5
#define ID_B 7
#define ID_C 9
const int id_arr={ ID_A, ID_B, ID_C, };
I know if I need to know the offset of ID_C in id_arr,
I can use a simple function like
int get_offset(id){
for(i=0;i<id_arr_num;++i){
if(id==id_arr[i]) return i;
}
}
But arr is const,
so I can know offset of ID_C will be 2 before runtime,
is any way to use macro or other way to know the offset before c runtime?
Rather than using ID's directly, use indexes that themselves are offsets:
enum {
IDX_A,
IDX_B,
IDX_C,
IDX_COUNT
};
const int id_arr={ 5, 7, 9 };
/* Error checking to make sure enum and array have same number of elements (from assert.h) */
static_assert((sizeof id_arr / sizeof *id_arr) == IDX_COUNT, "Enum/array mismatch");
Usage is simple:
id = id_arr[IDX_A];
Avoid using macros for that.
And you forgot to define id_arr_num.
No, there is no way of knowing this index before runtime, and avoid using global values as much as possible.
This function will give you the index of the variable you're looking for:
int get_offset(id, arr, size){
for(i = 0;i < size;++i)
if(id == arr[i]) return i;
}
I have
#define ADD 5
#define SUB 6
Can I print ADD and SUB given their values 5 and 6?
No.
The names of the defined symbols are removed by the preprocessor, so the compiler never sees them.
If these names are important at runtime, they need to be encoded in something more persistent than just preprocessor symbol names. Perhaps a table with strings and integers:
#define DEFINE_OP(n) { #n, n }
static const struct {
const char *name;
int value;
} operators[] = {
DEFINE_OP(ADD),
DEFINE_OP(SUB),
};
This uses the stringifying preprocessor operator # to avoid repetitions.
With the above, you can trivially write look-up code:
const char * op_to_name(int op)
{
size_t i;
for(i = 0; i < sizeof operators / sizeof *operators; ++i)
if(operators[i].value == op)
return operators[i].name;
return NULL;
}
you can do something like
printf("%d", ADD);
and it will print 5
The thing you have to remember about defines is:
Defines are substituted into the source code by the preprocessor before it is compiled so all instances of ADD in your code are substituted by 5. After the preprocessor the printf looks like this:
printf("%d", 5);
So to answer your question:
No you can't do it like that.
Yes, but not in via some reverse lookup mechanism wherein the value 5 is somehow symbolic in regards to the string "ADD". The symbols defined via a #define are tectually replaced by the pre-processor. You can however keep it simple:
const char *get_name(int value) {
switch(value) {
case ADD:
return "ADD";
case SUB:
return "SUB";
default:
return "WHATEVER";
}
}
#include <stdio.h>
int main() {
printf("%s = %d\n", get_name(ADD), ADD);
printf("%s = %d", get_name(SUB), SUB);
}
With modern C, since C99, this is even much simpler than unwind's answer by using designated initializers and compound literals
#define DEFINE_OP(n) [n] = #n
#define OPNAMES ((char const*const opNames[]){ \
DEFINE_OPT(ADD), \
DEFINE_OPT(SUB), \
})
inline
char const* getOp(unsigned op) {
size_t const maxOp = sizeof OPNAMES/ sizeof *OPNAMES;
if (op >= maxOp || !OPNAMES[op]) return "<unknown operator>";
else return OPNAMES[op];
}
Any modern compiler should be able then to expand calls as getOp(ADD) at compile time.