Insert variable value into a variable name in C - c

I have a type defined e.g.:
typedef enum {
T1,
T2,
T3,
T4,
T5,
T6,
LAST_IN_ENUM
} type1_t;
then another one using the above type e.g.:
typedef enum {
SUB1 = T1,
SUB2 = T2,
SUB3 = T3,
SUB4 = T4
} type2_t;
I would like to use then some fields of type2_t as input parameters to a function, but referring to its last character from a loop variable value, e.g. for SUB2 and SUB3:
for (i=2; i<4; i++) {
function1(SUBi)
}
What I don't know what the proper syntax is to pass the loop variable value to make it up SUBx (the above for loop syntax doe snot work, obviously).
Thanks a lot in advance if you have the solution.
I tried casting, converting to string, none of them worked.

You cant, I am afraid
You can only (if values are consecutive):
void bar(type2_t t2);
void foo(void)
{
for(type2_t t = SUB1; t <= SUB4; t++)
{
bar(t);
}
}
Or if they are not:
typedef enum {
T1 = 5,
T2 = 35,
T3 = 65,
T4 = 999,
T5,
T6,
LAST_IN_ENUM
} type1_t;
typedef enum {
SUB1 = T1,
SUB2 = T2,
SUB3 = T3,
SUB4 = T4
} type2_t;
void bar(type2_t t2);
void foo(void)
{
const type2_t t2Table[] = {SUB1, SUB2, SUB3, SUB4};
for(size_t t = 0; t < sizeof(t2Table) / sizeof(t2Table[0]); t++)
{
bar(t2Table[t]);
}
}

Related

C struct compound initialization without setting everything to zero

Is there any syntax similar to doing something like this
typedef struct foo
{
int X;
int Y;
int Z;
} foo;
int main()
{
// Initialize everything
foo Variable = (foo){
.X = 10;
.Y = 15;
.Z = 20;
};
// Assign the X and Y variables, but keep Z the same
Variable = (foo){
.X = 15;
.Y = 20;
// .Z stays the same
};
}
Would be nice to have this type of QOL syntax instead of having to type
int main()
{
foo Variable = {bla bla};
// Keep having to type Variable. to access struct members
Variable.X = 10;
Variable.Y = 15;
}
This gets really annoying with structs in structs i.e.
Struct1->Struct2.Struct3.Element.X = 10;
Struct1->Struct2.Struct3.Element.Y = 15;
No, C does not support this style of initialization or assignment.
If you want to access only a part of a structure, you need to express this explicitely.
EDIT:
You can get away with:
Variable = (foo){
.X = 15;
.Y = 20;
.Z = Variable.Z;
};
At least an optimizing compiler will just generate the operations for the changing elements. But it is more source than single assignments.
You can use the preprocessor to save your fingers (or copy/paste)...
struct {
int f1;
int f2;
struct {
int b1;
int b2;
int b3;
} bar;
} foo = {
1, 2, { 42, 43, 44 },
};
printf( "%d %d %d\n", foo.bar.b1, foo.bar.b2, foo.bar.b3 );
#define S foo.bar
S.b1 = 7;
S.b2 = 8;
printf( "%d %d %d\n", S.b1, S.b2, S.b3 );
#undef S

C flexible array define with another type instead of malloc

the general usage of flexible array is to use malloc to define the flexible array. I'm trying to explore defining the flexible array with another struct. An example
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
typedef struct {
test_base_t base;
float data[3];
} test_t;
As I understand, flexible array needs to be defined at the end of a struct. And clangd will give the following warning. -Wgnu-variable-sized-type-not-at-end
I just wanted to ask if anybody has done this before and is it safe? Or is there a better way to define flexible array size without alloc?
You can then wrap the usage of the object in a macro to static assert ext.base.data == ext.data before casting and passing to a general API consumes test_base_t. This way you can have the memory required in compile instead of allocing.
Edit
There seem to be a confusion on how I wanted to consume it, here is an example to demonstrate
#define SUM_BASE(test) \
sum_base(&test->base); \
_Static_assert(test->data == test->base.data);
float sum_base(test_base_t *base)
{
float sum = 0;
for (size_t i = 0; i < base->data_size; i++)
{
sum += base->data[i];
}
return sum;
}
test_t test = { .base = { .data_size = 3, }, .data = { 1, 2, 3, }, };
SUM_BASE((&test));
You cannot create actual instances of test_base_t with an initialized array, but you can create compound literals with an initialized array of a specified length and cast their address as test_base_t pointers. The layout and alignment of both structures should be compatible, given that they have exactly the same types, save for the flexible array length.
Here is an example:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
#define TEST_ARRAY(n) (test_base_t*)&(struct { uint64_t header; \
size_t data_size; \
float data[n]; })
float sum_base(const test_base_t *p) {
float sum = 0.F;
for (size_t i = 0; i < p->data_size; i++) {
sum += p->data[i];
}
return sum;
}
void print_test(const test_base_t *p) {
printf("%"PRIu64" %zu { ", p->header, p->data_size);
if (p->data_size) {
printf("%g", p->data[0]);
for (size_t i = 1; i < p->data_size; i++) {
printf(" %g", p->data[i]);
}
}
printf(" } sum=%g\n", sum_base(p));
}
int main() {
test_base_t *p1 = TEST_ARRAY(1){.data_size = 1, .data = {1}};
test_base_t *p2 = TEST_ARRAY(2){.data_size = 2, .data = {1, 2}};
print_test(p1);
print_test(p2);
print_test(TEST_ARRAY(3){.data_size = 3, .data = {1, 2, 3}});
print_test(TEST_ARRAY(4){.data_size = 4, .data = {1, 3, 5, 7}});
return 0;
}
Here is another approach, perhaps closer to your expectations, using a union with a base member with the flexible type and a parametric instance type with the appropriate array size:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
/* parametric type template using C macros */
/* structures with a flexible array can be members of union types */
#define test_base_t(...) \
union { \
test_base_t base; \
struct { \
uint64_t header; \
size_t data_size; \
float data[__VA_ARGS__]; \
}; \
}
float sum_base(const test_base_t *p) {
float sum = 0.F;
for (size_t i = 0; i < p->data_size; i++) {
sum += p->data[i];
}
return sum;
}
void print_test(const test_base_t *p) {
printf("%"PRIu64" %zu { ", p->header, p->data_size);
if (p->data_size) {
printf("%g", p->data[0]);
for (size_t i = 1; i < p->data_size; i++) {
printf(" %g", p->data[i]);
}
}
printf(" } sum=%g\n", sum_base(p));
}
int main() {
test_base_t(1) t1 = { .data_size = 1, .data = {1} };
test_base_t(2) t2 = { .data_size = 2, .data = {1, 2} };
/* the print_test function can be called without casts */
print_test(&t1.base);
print_test(&t2.base);
print_test(&((test_base_t(3)){.data_size = 3, .data = {1, 2, 3}}).base);
print_test(&((test_base_t(4)){.data_size = 4, .data = {1, 3, 5, 7}}).base);
return 0;
}
C 2018 6.7.2.1 3 says of a structure containing a flexible array member:
… such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.
Thus, the test_t type in the question violates this “shall” requirement, and C 2018 4 2 says that makes the behavior not defined by the C standard. A compiler could reject this code. If the compiler accepts it, the behavior of the program is not defined by the C standard.
As an example of what could go wrong (in that the C standard allows it), consider this code:
test_t test = { .base = { .data_size = 3, }, .data = { 1, 2, 3, }, };
printf("%g\n", test.base.data[0]);
Since test.base.data[0] was never assigned a value through that expression, and the standard does not define test.data to alias test.base.data, the compiler may assume the value of test.base.data[0] is uninitialized and hence unspecified, and this printf may use any value of the float type, even if test.base.data[0] and test.data[0] nominally refer to the same memory.
And in this code:
test_t test = { .base = { .data_size = 3, } };
for (int i = 0; i < 4; ++i)
test.base.data[i] = i+1;
test_t copy = test;
The compiler may assume that, since test.data was never initialized, it does not need to be copied to copy when initializing it from test.

How to build a MEX-file in MATLAB?

I need to use the following function in MATLAB code:
#include "mex.h"
#include <math.h>
#include <stdio.h>
float xFit_1931( float wave )
{
float t1 = (wave-442.0f)*((wave<442.0f)?0.0624f:0.0374f);
float t2 = (wave-599.8f)*((wave<599.8f)?0.0264f:0.0323f);
float t3 = (wave-501.1f)*((wave<501.1f)?0.0490f:0.0382f);
return 0.362f*expf(-0.5f*t1*t1) + 1.056f*expf(-0.5f*t2*t2)
- 0.065f*expf(-0.5f*t3*t3);
}
float yFit_1931( float wave )
{
float t1 = (wave-568.8f)*((wave<568.8f)?0.0213f:0.0247f);
float t2 = (wave-530.9f)*((wave<530.9f)?0.0613f:0.0322f);
return 0.821f*exp(-0.5f*t1*t1) + 0.286f*expf(-0.5f*t2*t2);
}
float zFit_1931( float wave )
{
float t1 = (wave-437.0f)*((wave<437.0f)?0.0845f:0.0278f);
float t2 = (wave-459.0f)*((wave<459.0f)?0.0385f:0.0725f);
return 1.217f*exp(-0.5f*t1*t1) + 0.681f*expf(-0.5f*t2*t2);
}
This function is coded in C language so I tried to build a MEX-file but I got this error message:
>> mex CMfunction.c
Building with 'lcc-win32'.
Error using mex
c:\users\ya7yawii\appdata\local\temp\mex_1695753636261_3832\cmfunction.obj
.text: undefined reference to '_expf'
Specified export _mexFunction is not defined
Missing exports. Aborting
I have just rewritten these functions in matlab code using the mathematical equations in the following paper Simple Analytic Approximations to the CIE XYZ
Color Matching Functions.
function int = xFit_1931(wave)
t1 = 0.0624.*(1-heaviside(wave-442.0))+0.0374.*heaviside(wave-442.0);
t2 = 0.0264.*(1-heaviside(wave-599.8))+0.0323.*heaviside(wave-599.8);
t3 = 0.0490.*(1-heaviside(wave-501.1))+0.0382.*heaviside(wave-501.1);
int = 0.362.*exp(-0.5.*((wave-442.0).*t1).^2)+1.056.*exp(-0.5.*((wave-599.8).*t2).^2)-0.065.*exp(-0.5.*((wave-501.1).*t3).^2);
end
function int = yFit_1931(wave)
t1 = 0.0213.*(1-heaviside(wave-568.8))+0.0247.*heaviside(wave-568.8);
t2 = 0.0613.*(1-heaviside(wave-530.9))+0.0322.*heaviside(wave-530.9);
int = 0.821.*exp(-0.5.*((wave-568.8).*t1).^2)+0.286.*exp(-0.5.*((wave-530.9).*t2).^2);
end
function int = zFit_1931(wave)
t1 = 0.0845.*(1-heaviside(wave-437.0))+0.0278.*heaviside(wave-437.0);
t2 = 0.0385.*(1-heaviside(wave-459.0))+0.0725.*heaviside(wave-459.0);
int = 1.217.*exp(-0.5.*((wave-437.0).*t1).^2)+0.681.*exp(-0.5.*((wave-459.0).*t2).^2);
end

union of value and function pointer

I am struggling with using unions. Why am I unable to pass the function pointer to where the union would be? Any help would be greatly appreciated.
Edit: removed a typedef
#include <stdio.h>
union U {
int(*fnPtr)(int);
int i;
};
enum E {
OPTION_0 = 0,
OPTION_1 = 1
};
int multiply_by_two (int x) {
return 2 * x;
}
int f (int x, enum E e, union U u) {
switch (e) {
case OPTION_0:
/* Return the sum */
return x + u.i;
case OPTION_1:
/* Return 2 * x */
return u.fnPtr (x);
}
}
int main (void) {
int a;
scanf ("%d", &a);
int b = f (a, OPTION_1, &multiply_by_two);
printf ("%d\n", b);
return 0;
}
First, this definition is not valid:
union U {
typedef int(*fnPtr)(int);
int i;
};
You can't have a typedef inside of a struct or union. Removing the typedef will give you a proper definition:
union U {
int(*fnPtr)(int);
int i;
};
The second problem is here:
int b = f (a, OPTION_1, &multiply_by_two);
The function f expects a union U, but you're passing it a int (*)(int). Those types are not compatible. Just because the union has a member of that type doesn't mean you can use that type wherever you would use the union. You need to create a union, set the proper field, then pass that to the function.
union U u;
u.fnPtr = multiply_by_two;
int b = f (a, OPTION_1, u);
In main function, try this:
int main()
{
...
union U myUnion;
myUnion.fnPtr = &multiply_by_two;
int b = f (a, OPTION_1, myUnion);
...
}
And also, the union definition is not correct, you need to remove typedef.
Just to add to other answers: this is usually called a variant data type, and it makes sense to keep the type enum in a struct, along with the union, since you will be passing it around all the time anyway.
So I would recommend placing both in a struct:
enum var_type
{
VAR_INT = 0,
VAR_FUNC = 1
};
struct variant
{
// contains the type of the stored value
enum var_type type;
// contains the actual value
union {
int(*fnPtr)(int);
int i;
};
};
And then you can have separate functions for creating each subtype, for simpler instantiation:
// wrap the int value in the variant struct
struct variant variant_create_int(int i)
{
return (struct variant){ .type = VAR_INT, .i = i };
}
// wrap the functino pointer in the variant struct
struct variant variant_create_func(int(*fnPtr)(int))
{
return (struct variant){ .type = VAR_FUNC, .fnPtr = fnPtr };
}
Meaning your main would do something like:
// create variant of type 'VAR_FUNC'
struct variant var = variant_create_func(&multiply_by_two);
and just pass the var struct forward.

MPI Program null pointer

I am trying to create an mpi program that will run my bellard function to calculate pi to ten thousand decimal places. When i run the program i am presented with the following errors, I have done some searching online and on the openMpi website, the problem appears to be a null pointer but i have looked through the code and cant seem to find it.
The error is:
Signal :segmentation fault(11)
Signal :address not mapped(1)
Failing at address : (nil)
Can anyone see the null pointer ?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi/mpi.h>
#define PRECISION 10000
float minus_one,one,two,three,four,five,six,seven,eight,nine,ten,
thirty_two,sixty_four,two_five_six,one_zero_two_four,
two_pow_six,recip_two_pow_six;
float *pi;
int rank,size;
void init(){
printf("\nstarted init function");
minus_one = -1.0;
one = 1.0;
two = 2.0;
three = 3.0;
four = 4.0;
five = 5.0;
six = 6.0;
seven = 7.0;
eight = 8.0;
nine = 9.0;
ten = 10.0;
thirty_two = 32.0;
sixty_four = 64.0;
two_five_six = 256.0;
one_zero_two_four = 1024.0;
two_pow_six = pow(two,6);
recip_two_pow_six = one/two_pow_six;
pi = 0;
printf("\nended init function");
return;
}
float *bellard(int start, int end,int rank){
float *terms;
float t,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,
t13,t14,t15,t16,t17,tx,ty,tz;
int offset = rank;
double start_k = start;
double end_k = end;
start_k = offset * (PRECISION /size);
end_k = (offset+1) * (PRECISION/size);
terms=0;
int k = start_k;
while( (k<PRECISION) && (k<end_k)){
t1 = k;
t2 = t1*ten;
t3 = t2+one;
t4 = two_five_six/t3;
t5 = t2+nine;
t6 = one/t5;
t7 = t2+three;
t8 = sixty_four/t7;
t9 = four*t1;
t10 = t9+one;
t11 = thirty_two/t10;
t12 = t2+five;
t13 = four/t12;
t14 = t2+seven;
t15 = four/t14;
t16 = t9+three;
t17 = one+t16;
t = t4+t6;
t = t-t8;
t = t-t11;
t = t-t13;
t = t-t15;
t = t-t17;
tx = pow(minus_one,k);
ty = pow(one_zero_two_four,k);
tz = tx/ty;
*terms = tz*t;
//pi = pi+terms;
k = k+1;
}
return terms;
}
int main(int argc, char** argv){
int i;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int elementsCount = 10000/(size-1);
float *workerPi;
float *tmpPi=0;
init(); //initialise variables
printf("\nim here 1");
if(rank == 0)
{
for(i=1; i < size; i++){
printf("\nin recv loop");
MPI_Recv(tmpPi,PRECISION,MPI_FLOAT,i,1,MPI_COMM_WORLD,&status);
*pi=*pi+*tmpPi;
}
}else{
//int i;
int start,end,slice,workers;
workerPi = malloc(sizeof(int)*elementsCount);
workers = size-1;
slice = 10000/workers;
start = (rank-1)*slice;
end = start+slice;
printf("\nWorker %d processing data %d to %d\n",rank,start,end);
workerPi = bellard(start,end,rank);
printf("\nworker finished pi");
MPI_Send(workerPi,slice,MPI_FLOAT,0,1,MPI_COMM_WORLD);
printf("\nworker sent stuff");
}
MPI_Finalize();
return 0;
}
In the bellard function, terms is declared as a pointer to float
float *terms;
and initialized to zero (aka null) a few lines down
terms=0;
Towards the end of the while loop, it is dereferenced:
*terms = tz*t;
The statement *terms is a null pointer dereference and will crash. It is essentially asking to store the result of tz*t into memory address zero, which is not a valid memory address.
The fix may be to declare and use terms as a float, not a pointer to a float (float*).

Resources