C Typedef Struct / Union auto-cast - c

Im having a small math library for 3d vector and Im trying to "unify" it.
Instead of having multiple typedef struct for vector3f, vector3i, color3, angles etc... Im trying to put everything inside the same struct like this:
typedef struct
{
union
{
float x;
float r;
float ax;
int x_int;
};
union
{
float y;
float g;
float ay;
int y_int;
};
union
{
float z;
float b;
float az;
int z_int;
};
} vec3;
Everything works peachy as long as the type is float, however when it falls to int Im having some strange values (which is understandable). My question is: Is there a way to cast directly/automatically inside the structure definition or I have to create extra functions to typecast between float and int?
Due to the answers below, maybe I should modify my original question to the following:
What is the best way to "unify" (and by unify I mean have like 1 struct) to be able to handle at the same time the following:
vector3f (float x,y,z)
vector3i (int x,y,z)
RGB (float r,g,b)
RGB (unsigned char r,g,b)
euler angle (ax, ay, az)
Thanks in advance!

If you mean that you want to put '360.0f' into float z of a union and have int z_int == 3, or vice versa, you can't. That is not the purpose of a union, and the binary representation of 3 (an integer) and 3.0 (a floating point value) are dissimiliar.
However, you could just remove the int and cast one of the floats to an int.

#include <stdio.h>
#include <stdlib.h>
typedef struct genericStruct
{
void *valueOne;
void *valueTwo;
}GS;
int main()
{
GS *gs = malloc(sizeof(*gs));
int valueInt = 10;
float valueFloat = 3.141592653589;
int *inputIntPtr = (int*)malloc(sizeof(int));
float *inputFloatPtr = (float*)malloc(sizeof(float));
void *voidPtr = NULL;
*inputIntPtr = valueInt;
*inputFloatPtr = valueFloat;
voidPtr = inputIntPtr;
gs->valueOne = voidPtr;
int *outputIntPtr = (int*)malloc(sizeof(int));
outputIntPtr = gs->valueOne;
printf("Input ptr = %d\n", *inputIntPtr);
printf("Output ptr = %d\n", *outputIntPtr);
voidPtr = inputFloatPtr;
gs->valueTwo = voidPtr;
float *outputFloatPtr = (float*)malloc(sizeof(float));
outputFloatPtr = gs->valueTwo;
printf("Input ptr = %f\n", *inputFloatPtr);
printf("output ptr = %f\n", *outputFloatPtr);
free(gs);
free(inputIntPtr);
free(inputFloatPtr);
free(outputIntPtr);
free(outputFloatPtr);
return 0;
}
And this what I meant by using void types.

This is a small piece of code that i wrote for you.It should do the job.I hope i was able to do what you asked for...
typedef struct{
void *ptr1;
void *ptr2;
void *ptr3;
}VEC;
main(){
VEC v ;
VEC *ptr;
int a = 5;
double b = 6;
float c = 7;
v.ptr1 = NULL;
v.ptr2 = NULL;
v.ptr3 = NULL;
ptr = &v;
v.ptr1 = (int *)&a;
ptr->ptr1 = (int *)&a;
v.ptr2 = (double *)&b;
ptr->ptr2 = (double *)&b;
v.ptr3 = (float *)&c;
ptr->ptr3 = (float *)&c;
printf("%d\n",*(int *)v.ptr1);
printf("%d\n",*(int *)(ptr->ptr1));
printf("%lf\n",*(double *)v.ptr2);
printf("%lf\n",*(double *)(ptr->ptr2));
printf("%f\n",*(float *)v.ptr3);
printf("%f\n",*(float *)(ptr->ptr3));
}

Or change all variables to void pointer type and then cast them to float or integer. Is it OK?

Related

Cast void pointer to double without knowing its type in C

I need to write a function which takes as parameters a void pointer (representing an array) and an integer which represents the length of the array. In the function, I need to cast this void pointer into a double one. The problem is that the void pointer can represent an array of integers or floats or doubles.
So the following is obviously not working in case the void pointer represents an array of integers or floats:
void foo(void *v,int n){
double *values;
values=(double*)v;
for(i=0;i<n;i++)
printf("%f\n",values[i]);
}
so this will print the correct output:
foo((double[]){1,2,3,4},4);
and this will print a wrong output:
foo((int[]){1,2,3,4},4);
foo((float[]){1,2,3,4},4);
So... can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles? And is it necessary to have the length of the array or I can calculate it somehow?
P.s. without using callbacks
can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles?
No, you cannot. You need to pass the type information somehow.
And is it necessary to have the length of the array or I can calculate it somehow?
It's necessary to pass the length.
You can "hide" the information inside a struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum etype { INTEGER, FLOAT, DOUBLE };
struct data {
void *values;
size_t n;
enum etype type;
};
void foo(struct data *x) {
int *xd = x->values;
float *xf = x->values;
double *xg = x->values;
for (int k = 0; k < x->n; k++) {
switch (x->type) {
default: printf("%g ", xg[k]); break;
case FLOAT: printf("%f ", xf[k]); break;
case INTEGER: printf("%d ", xd[k]); break;
}
}
puts("");
}
int main(void) {
struct data x;
x.values = malloc(4 * sizeof(int));
((int*)(x.values))[0] = 42;
((int*)(x.values))[1] = -1;
((int*)(x.values))[2] = 0;
((int*)(x.values))[3] = 999;
x.n = 4;
x.type = INTEGER;
foo(&x);
x.values = calloc(4, sizeof(float));
x.type = FLOAT;
float tmp = 3.14159;
memcpy(((float*)(x.values))+1, &tmp, sizeof (float));
foo(&x);
free(x.values);
x.values = calloc(4, sizeof(double));
x.type = DOUBLE;
((double*)(x.values))[2] = 2.7182818;
foo(&x);
free(x.values);
}
See code running on ideone

How to pass pointers to vector extensions in C

I'm trying to use GCC's vector extensions, the exact code that I tried is:
typedef float Vector4 __attribute__ ((vector_size (16)));
void defVector(Vector4* v, float x,float y,float z,float w){
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
}
int main(int argc, char* argv){
Vector4 a;
defVector(&a, 1, 2, 3, 4);
}
and keep getting errors:
incompatible types when assigning to type ‘Vector4 {aka __vector(4) float}’ from type ‘float’
v[0] = x;
Can't dereference it too or I get another error.
I would like to not copy the entire thing to the function stack every time I use it, and it's a necessity to make pointers to the return values like
int someFunc(Vector4 v, Vector4* r){
...
r[0] = return_value;
return 0;
}
I tried everything I know to access the values inside the funtion.
What I'm missing here?
Based on the OP's example in which a local function gets a "vector-extension" pointer:
#include <stdio.h>
#include <stdint.h>
typedef float Vector4 __attribute__ ((vector_size (16)));
void defVector(Vector4 *v,float a, float b);
void defVector(Vector4 *v,float a, float b){
v[0] = *(Vector4*)&a;
v[1] = *(Vector4*)&b;
a = *(float*)&v[0] + 1.2;
b = *(float*)&v[1] + 2.1;
printf("%f,%f,%u",a,b,\
(uint32_t)sizeof(Vector4)/(uint32_t)sizeof(float));
}
int main(void) {
static Vector4 vectorA;
static float x1 = 3.4;
static float x2 = 4.3;
defVector(&vectorA,x1,x2);
}
This code will print (demo): 4.6,6.4,4 , so the value of two float were assigned to two units (being the number of units sizeof(Vector4)/sizeof(float)) of a Vector4 type variable.

warning: assignment from incompatible pointer type [-Wincompatible-pointer-types] qt1.function = &H1

I doing integration of a complex function using gsl library in C programming language. In this code I had to declare two variables using pointer that I have done successfully. But I am facing a problem when I pass these variables in main function.
Please help me out.
My code is being written here:
struct har{
double t;
double k;
double x;
};
#include"str.h"
struct har H1( void * params, float q , int p )
{
struct har *p_params = (void *)params;
float mu=2;
double x =p_params ->x ;
double t = p_params -> t;
double k = p_params -> k;
//printf("%d",k);
struct har H1 = {x*cos(t*x)/(pow((mu*t*k),2)+pow(x,2))};
return H1;
}
double H (double x,void * params )
{
double e;
double t = *(double *) params;
//printf("%f\n",t);
//struct har t1,z;
//double t = z.params ->t1;
double H = (pow(e,-x)/x) ;//I(x,&t)*(sin(x*t));
return H;
}
#include<stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include"H.h"
#include"H1.h"
int
main (void)
{
gsl_integration_workspace * w
= gsl_integration_workspace_alloc (10000);
struct har t,k;
double x, qtr, qbartr, qdottr, qddotr,q7r, qatr, qbtr, qt1r, error;
double expected = -4.0;
double a1 = 1e-14;
double a= 150;//150;
double pi = 3.141;
double b = 1.05263;
double mu = (2*pi)/b;
double q0=0;
double p0=6.5;
double om=7.07;
double tau=0.141;
double gamma = 0.180;
for(int m=2; m<4; m++)
{
float t = 4.14937*(m-1);
gsl_function qt;
qt.function = &H;
qt.params =&t;
gsl_integration_qags (&qt, a1, a, 0,1e-7, 10000, w, &qtr, &error);
// printf ("qtresult = % .18f\n\n", qtr);
for(int k=1; k<=2; k++)
{
{
struct har item = {x,t,k};
struct har *p_params = &item;
double gama=gamma/((mu*k*tau)+1);
// printf("gama = % .18f\n", gama);
gsl_function qt1;
qt1.function = &H1;
qt1.params = &p_params;
// qt1.params = &k;
gsl_integration_qags (&qt1, a1, a, 0,1e-7, 10000, w, &qt1r, &error);
printf("qt1result= % .18f\n", qt1r);
}
}
gsl_integration_workspace_free (w);
return 0;
}
In above code I had four file by namely code.c, str.h, H1.h and H.h. Where H1 and H contains two user defined functions and str is a file for structure and code.c is my main to compile.
Thanks for your time and observation.
Regards
Ramesh
The field qt1.function has type double (*)(double, void *). The function H1 which you attempt to assign to this field has type struct har (*)( void *, float, int).
These types are incompatible as the number of arguments, the types of the arguments, and the return type are all different. As it is right now, you have two parameters called p and q that are never being used. Also, the struct har you construct as a return value doesn't even set all the fields, just the first one, so why are you even returning a struct?
In order for H1 to work with gsl_function, is must accept a double and a void * and return a double. The x value corresponds to the double that is passed in, so you don't need that in your struct. Since you're also only building a single value to return, that's what you return.
struct har{
double t;
double k;
};
double H1( double x, void *params)
{
struct har *p_params = params; // no need to cast to/from void *
float mu=2;
double t = p_params->t;
double k = p_params->k;
return x*cos(t*x)/(pow((mu*t*k),2)+pow(x,2));
}
Also, you're not setting the values of qt1 properly:
qt1.params = &p_params;
Since p_params is a struct har *, its address is a struct har **. Your function however is expecting a struct har * to be passed in. So change this to the address of the struct, not the address of a pointer pointing to it:
qt1.params = &item;
You also have a mismatch when you set qt.params. You're giving it a float *, but your function H is expecting a double *. Just change the type of t to match:
double t = 4.14937*(m-1);

Using Custom Vectors in C

I'm fairly new to C/C++, but I'm trying to debug some code. It uses a vector that someone had called CART8 and is structured as such:
typedef struct crt8 {
double x;
double y;
double z; } CART8;
Now my question is this. How do I create and populate an instance of an vector of type CART8 called vector1? I've read through a lot of material, and even found a site that indicate how you would create the vector...as indicated above, but no information on HOW to actually use it.
typedef is used extensively in C to refer to struct variables without specifying the struct prefix, for example if I had:
struct vector {
double x;
double y;
double z;
};
than to initialize it I'd have to do:
struct vector vector1;
vector1.x = 1.11;
vector1.y = 1.22;
vector1.z = 1.33;
But if I used a typedef in the declaration:
typedef struct vector {
double x;
double y;
double z;
} vector_type;
than I could simplify this initialization like so (note the struct prefix is not needed now):
vector_type vector1;
vector1.x = 1.11;
vector1.y = 1.22;
vector1.z = 1.33;
Of course, I could still use the full struct vector initialization in this case as well
So in your case:
#include <stdio.h>
typedef struct crt8 {
double x;
double y;
double z;
} CART8;
int main(int argc, char** argv)
{
CART8 vector1;
vector1.x = 2.526;
vector1.y = 3.416;
vector1.z = 4.32;
printf("%f %f %f\n", vector1.x, vector1.y, vector1.z);
}
Alternatively, you can always resort to the original struct definition:
#include <stdio.h>
typedef struct crt8 {
double x;
double y;
double z;
} CART8;
int main(int argc, char** argv)
{
struct crt8 x;
x.x = 2.341;
x.y = 3.43;
x.z = 4.521;
printf("%f %f %f\n", x.x, x.y, x.z);
}
You wrote:
typedef struct crt8 {
double x;
double y;
double z;
} CART8;
This defined a new 'type'. The 'typename' is struct crt8 or the alias you defined CART8. This is how you instantiate an object from that type in C:
struct crt8 myVector;
or you can use the alias 'CART8' that you've defined:
CART8 myVector;
Either way, this is how you populate the 'members' of your object:
CART8 x; // Creation of object
x.x = 100;
x.y = 101;
x.z = 102;
Here is a demonstrative program that shows various ways how objects of the structure can be created, initialized, and used.
#include <stdio.h>
#include <math.h>
typedef struct crt8 {
double x;
double y;
double z; } CART8;
int main( void )
{
CART8 vector1 = { 1.1, 2.2, 3.3 };
CART8 vector2 = { .x = 1.1, .y = 2.2, .z = 3.3 };
CART8 vector3;
vector3.x = 1.1;
vector3.y = 2.2;
vector3.z = 3.3;
CART8 vector4 = vector1;
CART8 vector5 = { vector1.x + vector2.z, vector1.y + vector2.y, vector1.z + vector2.x };
printf( "vector5 = { %lf, %lf, %lf }\n", vector5.x, vector5.y, vector5.z );
printf( "Magnitude = %lf", sqrt( pow( vector1.x, 2 ) + pow( vector1.y, 2 ) + pow( vector1.z, 2 ) ) );
return 0;
}
The output is
vector5 = { 4.400000, 4.400000, 4.400000 }
Magnitude = 4.115823

Initializating struct error: 'theGrid' being used without being initialized

I am trying to create a 3d grid for my OpenCl/GL fluid. The problem Im having is that for some reason the my grid initialization function does not work properly. Here is my *.h, *.c setup and (at the end) call in main:
(grid.h):
#if RunGPU
#define make_float3(x,y,z) (float3)(x,y,z)
#define make_int3(i,j,k) (int3)(i,j,k)
#else
typedef struct i3{
int i,j,k;
} int3;
typedef struct f3{
float x,y,z;
} float3;
#define __global
#define make_float3(x,y,z) {x , y , z}
#define make_int3(x,y,z) {x , y ,z}
#endif
typedef struct grid3 * grid3_t; // u,v,w
typedef struct grid * grid_t; // p
struct grid3 {
__global float3* values_;
__global float * H_;
__global float * h_;
int dimx_;
int dimy_;
int dimz_;
} ;
struct grid {
__global float * values_;
int dimx_;
int dimy_;
int dimz_;
};
void grid3_init(grid3_t grid,__global float3* vel,__global float* H,__global float *h, int X, int Y, int Z);
(grid.c):
void grid3_init(grid3_t grid,__global float3* val,__global float* H,__global float *h, int X, int Y, int Z){
grid->values_ = val;
grid->H_ = H;
grid->h_ = h;
grid->dimx_ = X;
grid->dimy_ = Y;
grid->dimz_ = Z;
}
In main im initializing my grid like so:
int main(int argc, char** argv)
{
const int size3d = Bx*(By+2)*Bz;
const int size2d = Bx*Bz;
float3 * velocities = (float3*)malloc(size3d*sizeof(float3));
float * H = (float*)malloc(size2d*sizeof(float));
float * h = (float*)malloc(size2d*sizeof(float));
for(int i = 0; i < size3d; i++){
float3 tmp = make_float3(0.f,0.f,0.f);
velocities[i] = tmp;
if(i < size2d){
H[i] = 1;
h[i] = 2;
}
}
grid3_t theGrid;
grid3_init(theGrid, velocities, H, h, Bx, By, Bz); // <- ERROR OCCURS HERE
}
The error im getting is during runtime - "Run-Time Check Failure #3 - The variable 'theGrid' is being used without being initialized". But thats precisely the job of grid3_init?
As im trying to write code to work for both Host and GPU I have to sacrifice the use of classes and work strictly with structs - which I have less experience with.
At this point I dont really know what to google either, I appriciate any help i can get.
struct grid3 theGrid;
grid3_init(&theGrid, velocities, H, h, Bx, By, Bz);
You need to create grid3 instance and pass its pointer to grid3_init. Your existing code just uses uninitialized pointer.

Resources