Returning a struct in a void func() - c

I'm trying to compile my code from the old MS-DOS days and this doesn't seem to work with GCC:
typedef struct { int x,y,z; } vector;
inline void vect_add(vector& c,vector a, vector b)
{
c.x=a.x+b.x;
c.y=a.y+b.y;
c.z=a.z+b.z;
}
Basically I'm trying to return a struct which is later used as vector.x etc instead of rewriting it as a pointer to struct and rewriting all as vector->x etc
see (vector& c,

That is possibly valid C++, but it's not valid C.
In C, you need to use a pointer, a global var, or actually return a struct.
typedef struct { int x, y, z; } vector;
inline void vect_add(vector* c, vector a, vector b)
{
c->x = a.x + b.x;
c->y = a.y + b.y;
c->z = a.z + b.z;
}
vect_add(&c, a, b);

Related

Function Pointer with void* return and void* parameters

I wrote a function pointer that has all void* so that it can be used for any numeric value
int
float
double.
But it is working only for the int addition function
For float and double addition functions, it throws compile time error.
Why is that so ?
If you uncomment the last two printf lines, you would receive error
#include<stdio.h>
int int_add(int x, int y) {
return x + y;
}
float float_add(float x, float y) {
return x + y;
}
double double_add(double x, double y) {
return x + y;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
printf("Sum= %d\n",(int*) do_operation(int_add, 1, 2));
/*printf("Sum= %f\n",(float*) do_operation(float_add, 1.20, 2.50));*/
/*printf("Sum= %lf\n",(double*) do_operation(double_add, 1.20, 2.50));*/
}
void * is a pointer type. You're not passing pointers, you're passing values, so that's not going to compile. It accidentally "works" for int because pointers themselves are represented as integers by most C compilers.
If you pass pointers to int, float, and double instead of the int, float, and double themselves, you will avoid that compiler error. You'd also need to change int_add and friends to take pointers, and you'd have to make sure you dereferenced the pointers before using them. You'll also have to return pointers, which means you'll have to malloc some memory on the heap, because the stack memory assigned to your local variables will be invalid once your function exits. You'll then have to free it all later... in the end, this is going to result in something considerably more complicated than the problem it appears you are trying to solve.
I have to ask why you are trying to do this? C is really not the best language for this type of pattern. I'd suggest just calling the int_add, float_add, etc. functions directly instead of trying to abstract them in this way.
So as per #charles-srstka suggestion I rewrote the code and then it worked as I wanted
#include<stdio.h>
#include<stdlib.h>
int* int_add(int *x, int *y) {
int *c = (int *)malloc(sizeof(int));
*c = *(int*)x + *(int*)y;
return c;
}
float* float_add(float *x, float *y) {
float *c = (float*)malloc(sizeof(float));
*c = *(float*)x + *(float*)y;
return c;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
int a = 1;
int b = 2;
int *c;
c = do_operation(int_add, &a, &b);
printf("%d\n",*c);
free(c);
float x = 1.1;
float y = 2.2;
float *z;
z = do_operation(float_add, &x, &y);
printf("%f\n",*z);
free(z);
}

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.

Return statement with more than one arguments

After compiling my C code with -Wall activated, the following warnings appeared
left operand of comma operator has no effect
which are related with the the multiple arguments presented in my return statements. The story is the following:
Assume to have a bunch of dynamically allocated 3D arrays (A,B and C) and want to do some manipulation on them. The arrays are defined as pointer to pointer to pointer and allocated using malloc (the standard procedure). The manipulation of them will occur in seperate functions. For some reason I declare the function as a triple pointer and as follow:
***func( double ***A, double ***B, double ***C)
{
do some work here on A, B and C
return(A, B, C);
}
I know that the arrays are passing into the function as reference so essentially there is no need of returning something from this function. But, can you tell me why someone would declare a function this way. This staff confuses me. Thanks in advance
return(A, B, C) is not C, you can use a struct to return more than one arguments.
struct array3d{
double* A;
double* B;
double* C;
};
struct array3d* func(struct array3d* p) {
/* do some work here on p->A, p->B and p->C */
return p;
}
Here is an working example with *** pointers:
#include <stdio.h>
#include <malloc.h>
struct array3d {
double*** A;
double*** B;
double*** C;
};
struct array3d* func(struct array3d* p) {
/* do some work here on A, B and C */
***p->A /= 42.0;
***p->B /= 42.0;
***p->C /= 42.0;
return p;
}
int main()
{
struct array3d arr;
struct array3d* p_arr;
double A[] = { 1.0, 3.0}; // ...
double B[] = {-1.0, -2.0};
double C[] = { 2.0, 4.0};
double* p1A = A;
double* p1B = B;
double* p1C = C;
double** p2A = &p1A;
double** p2B = &p1B;
double** p2C = &p1C;
arr.A = &p2A;
arr.B = &p2B;
arr.C = &p2C;
p_arr = func(&arr);
printf("(A = %f, B = %f, C = %f)\n", ***p_arr->A, ***p_arr->B, ***p_arr->C);
return 0;
}
The code
***func( double ***A, double ***B, double ***C)
{
do some work here on A, B and C
return(A, B, C);
}
is simply wrong, even though it compiles:
If the function returns everything via its arguments A, B, and C, it should not have a return type. I. e., it should be declared to return void:
void func( double ***A, double ***B, double ***C) {
The syntax return(A, B, C) does not do what you think it does. It does not construct a list, or pass three values to return. Instead, it evaluates the expression A, throws its value away, evaluates B, throws its value away, evaluates C, takes the value of C as the value of the expression (A, B, C), and finally returns that value from the function. (Google "C comma operator" for more information.)
If your function is declared as returning void (as it probably should be), there is simply no need for a return statement.

Casting data array to compatible struct

I'm in a situation where my code receives data from somewhere beyond my control in the form of a long list of floats.
These numbers get distributed to various functions
void myfunc(struct floatstruct* fs);
that take structs of the following form:
struct floatstruct
{
float a;
float b;
float c;
};
You get the idea.
I was wondering if there is a way to safely cast the array of floats to floatstruct to pass the data directly on to myfunc. I can add alignment attributes to floatstruct if necessary.
Example of desired behaviour:
struct mystruct1
{
float a;
float b;
float c;
};
struct mystruct2
{
float x;
float y;
};
extern void myfunc1(mystruct1*);
extern void myfunc2(mystruct2*);
void process_data(float* numbers)
{
myfunc1((struct mystruct1*)numbers);
myfunc2((struct mystruct2*)(numbers + 3));
}
The ideal solution is surely to change the system. But I'm looking for solutions within the given parameters.
Here's what I would do, given your peculiar requirements: ( I say this because 3 new floats here or there will make literally no noticeable difference unless you plan to use this on an arduino or phone or if you plan on having like tens of thousands...)
Anyways:
struct floatstruct
{
float (*a[3]);
};
{
int i;
struct floatstruct aStruct;
struct floatstruct bStruct;
float *num = numbers;
for (i = 0; i < 6; i++) {
if (i < 3)
aStruct.a[i] = num;
else
bStruct.a[i-3] = num;
num++;
}
myfunc1(&aStruct);
myfunc2(&bStruct);
}
Union could be what you need:
#pragma pack(sizeof(float))
struct mystruct1
{
float a;
float b;
float c;
};
struct mystruct2
{
float x;
float y;
};
#pragma pack()
typedef union
{
mystruct1 struct1;
mystruct2 struct2;
}structsUnion;
void myfunc1(structsUnion* values)
{
values->struct1.a; // to access members
}
void myfunc2(structsUnion* values)
{
values->struct2.x; // to access members
}
void process_data(float* numbers)
{
myfunc1((structsUnion*)(numbers));
myfunc2((structsUnion*)(numbers));
}

how to pass array as function arguments in C?

how to pass array as arguments in C?
int a,b,c[10];
void Name1(int x, int y, int *z)
{
a = x;
b = y;
c = z;
}
I try to pass it as argument, but it does not build, how to fix it?
And is the declaration of void Name1(int x, int y, int *z); is the same as void Name1(int x, int y, int z[])? does the void Name1(int x, int y, int z[]) will be treated as void Name1(int x, int y, int *z); by compiler?
When you pass array as an argument to function it decays as an pointer to its first element.
So,
void Name1(int x, int y, int *z)
will work.
But arrays are not assignable so:
c = z;
does not work, you will need to explicitly copy each array element from source to destination.
Doing c = z;, you're assigning to a non l-value, which is not allowed. It's like doing &c[0] = &z[0];.
There are a couple of answers here, but I don't think any of them are completely sufficient, so...
basically you can either copy the array or use the pointer, but either way you will need to keep track of the length.
int a,b, *c, len;
void Name1(int x, int y, int *z, int z_len)
{
a = x;
b = y;
c = z;
len = z_len;
}
//usage:
int arr[5];
Name1(1,2,arr /* or &arr[0] ,*/, sizeof(arr )/ sizeof (int));
if you never need to add items this will be sufficient... If you do it gets more complicated...
it is important to keep the length around so that you know how many elements you have, even if you are going to copy them.
c=z; is invalid
c pointer doesnt have memory to save the z address.
you can say:
int a,b,*c;
c=(int *)calloc(10,sizeof(int) );
void Name1(int x, int y, int *z)
{
a = x;
b = y;
c = z;
}

Resources