Typecasting an array in C - arrays

I was reading FFMPEG source code on extracting audio and I found these macros. What do these macros do?
#define REINTERPRET_CAST(type, variable) C_CAST(type, variable)
#define STATIC_CAST(type, variable) C_CAST(type, variable)
#define C_CAST(type, variable) ((type)variable)
//used like this
int value = 0;
int sampleIndex = 0;
uint8_t* buffer = calloc(50, sizeof(uint8_t));
value = REINTERPRET_CAST(uint8_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int16_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int32_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int64_t*, buffer)[sampleIndex];
int ret = STATIC_CAST(float, *REINTERPRET_CAST(double*, &value));

//used like this
Used like in this code they do nothing meaningful - convert pointer to int and assign to int vartable (abstracting from the wrong syntax)
If they are used like this:
uint64_t value = *REINTERPRET_CAST(int64_t*, buffer + sampleIndex);
BTW the macro is wrong as well
#define C_CAST(type, variable) ((type)(variable))
Then it is called pointer punning and it invokes Undefined Behaviour violating strict aliasing rules.
It should be done this way:
#define pune(var, X) _Generic((var), \
uint16_t *: pune16, \
uint32_t *: pune32, \
uint64_t*: pune64 \
)(var, X)
uint16_t pune16(uint16_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
uint32_t pune32(uint32_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
uint64_t pune64(uint64_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
example usage:
void foo(void *v)
{
uint32_t x;
x = pune(&x, v);
printf("%"PRIu32"\n,", x);
}

Related

Can I cast a variable to a type decided during execution in C

int* push_back_int(intVector* target, int push)
{
target->length++;
target->val = (int *)realloc(target->val, target->length * sizeof(int));
target->val[target->length - 1] = push;
return &target->val[target->length - 1];
}
float* push_back_float(floatVector* target, float push)
{
target->length++;
target->val = (float *)realloc(target->val, target->length * sizeof(float));
target->val[target->length - 1] = push;
return &target->val[target->length - 1];
}
Is there any way that I can hold a variable to replace the cast to int* or float* so that i can reuse the same code for multiple variable types using void*
No. In C the type is only available at compile-time.
You can use void * to pass data back and forth but you need to retain the element size. This approach is referred to as non-type safe (compiler will not catch the wrong "type", say, switching iq and fq below, which will then blow up most impressively at run-time when you get it wrong). Note how calling code handles the cast.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct queue {
size_t push_length;
void *val;
size_t length;
};
void *push_back(struct queue *target, void *push) {
size_t offset = target->length * target->push_length;
target->length++;
void *tmp = realloc(target->val, target->length * target->push_length);
if(!tmp) {
// error handling
return NULL;
}
target->val = tmp;
return memcpy((char *) target->val + offset, push, target->push_length);
}
int main() {
struct queue fq = { sizeof(float), NULL, 0 };
push_back(&fq, &(float) { 2.718 });
push_back(&fq, &(float) { 3.142 });
for(unsigned i = 0; i < fq.length; i++) {
printf("%u: %f\n", i, ((float *) fq.val)[i]);
}
struct queue iq = { sizeof(int), NULL, 0 };
push_back(&iq, &(int) { 1 });
push_back(&iq, &(int) { 2 });
for(unsigned i = 0; i < iq.length; i++) {
printf("%u: %d\n", i, ((int *) iq.val)[i]);
}
}
and the output:
0: 2.718000
1: 3.142000
0: 1
1: 2
Your platform may require specific alignment for each element of val (i.e. for type T push_length = sizeof(T) % alignof(T) ? (sizeof(T) / alignof(T) + 1) * alignof(T) : sizeof(T)).
Can I cast a variable to a type decided during execution (?)
Yes, in some cases that support variable length array.
(double (*)[r]) is a cast to a type determined at run time. Demonstrative code follows:
int r = rand();
double a[r];
double (*b)[r] = &a;
unsigned char *data = malloc(sizeof a);
b = data; // warning: assignment to 'double (*)[r]' from incompatible pointer type 'unsigned char *' [-Wincompatible-pointer-types]
b = (double (*)[r]) data; // OK
(void) b;
In OP's code, the cast nor the sizeof(type) are not needed.
Use target->val = realloc(target->val, target->length * sizeof(target->val[0])); for both.
Only difference remaining in push_back_...() is the function name and signature.
Is there any way that I can hold a variable to replace the cast to int* or float* so that i can reuse the same code for multiple variable types using void*.
Any object pointer can be held in a void *. Yet that void * does not certainly retain anything to denote the type from which it is assigned. Auxiliary data needed. In OP's case, the size of the type would be enough if the size was consistent per vector.
typedef struct {
size_t object_size;
size_t length;
void *val;
} gVector;
// Pass in the address of the object to push
void* push_back_g(gVector* target, const void *push) {
void *p = realloc(target->val, target->object_size * (target->length + 1u));
if (p) {
target->val = p;
return memcpy((unsigned char *)val + target->object_size * target->length++,
push, target->object_size);
}
// Handle error with TBD code
return NULL;
}
Alternative we could pass in the size per push call and store that too.
Yet in both cases, code loses type checking.
With _Generic, code could handle various pre-determined select types with common code. Yet it seems OP wants any type.
C does not have runtime type information (RTTI) so you would have to hack that out manually by introducing an enum or similar. However, I would not encourage type generic programming with enums + void pointers in modern C programming since it is type unsafe and clunky.
We could use macros to generate type-generic code based on a number of supported types, kind of like a poor man's version of C++ templates. But that creates code which is very hard to read and maintain, so it isn't advisable either. Just for the record, it might look like this:
// NOT RECOMMENDED PRACTICE
#define SUPPORTED_TYPES(X) \
X(int) \
X(float) \
#define vector_define(type) \
typedef struct \
{ \
type* val; \
size_t length; \
}type##Vector;
SUPPORTED_TYPES(vector_define)
#define push_back_define(type) \
type* push_back_##type (type##Vector* target, type push) \
{ \
target->length++; \
target->val = realloc(target->val, target->length * sizeof(type)); \
target->val[target->length - 1] = push; \
return &target->val[target->length - 1]; \
}
SUPPORTED_TYPES(push_back_define)
As you can see it starts to look like a different language and the code is pretty alien to read for anyone who isn't used at seeing "X-macros".
In this case the best solution is perhaps to write a version using void* but to wrap it in a type safe macros utilizing _Generic. Your vector could then be implemented as a single type-generic ADT. Not a separate one for int, float and so on. As for how to do that proper, it's too long an answer for SO - a place to start would be to read up on How to do private encapsulation in C?.
A simple example of how to use _Generic without creating a proper ADT:
#include <stdio.h>
void push_back_int (int* target, int push)
{ puts(__func__); }
void push_back_float (float* target, float push)
{ puts(__func__); }
#define push_back(arr,item) \
_Generic((arr), \
int*: push_back_int, \
float*: push_back_float) \
((arr), (item) )
int main (void)
{
int* i_arr;
int i_item = 5;
push_back(i_arr, i_item);
float* f_arr;
float f_item = 123.0f;
push_back(f_arr, f_item);
}

Why do i get invalid use of void expression?

I want to recreate vectors in c, and i get an invalid use of void expression error. I have tried it like this.
typedef struct {
void *data;
int size;
int capacity;
} vec;
#define vec_new(name, type) vec name; (name).size = 0; (name).capacity = 8; {\
void *vec_temp; vec_temp = calloc(8, sizeof(type));\
while (vec_temp == NULL) { vec_temp = calloc(8, sizeof(type)); }\
(name).data = vec_temp;\
}
#define vec_set(vec, index, value, type) *( (type*) (vec).data[(index)] ) = value;
#define vec_get(vec, index, type) *( (type*) (vec).data[(index)] )`
I get the error in the set and get macros
You are indexing a void* type with the way things are. You are typecasting (vec).data[(index)] to type*, you should be casting ((vec).data) to type*
Try this instead:
#define vec_set(vec, index, value, type) ((type*) (vec).data)[(index)] = value;
#define vec_get(vec, index, type) (((type*) (vec).data)[(index)])
You are getting invalid use of void expression cos we cant do void* arithmatics and dereference ! you need to cast the data struct member and you did it wrong.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *data;
int size;
int capacity;
} vec;
#define vec_new(name, type) vec name; (name).size = 0; (name).capacity = 8; {\
void *vec_temp; vec_temp = calloc(8, sizeof(type));\
while (vec_temp == NULL) { vec_temp = calloc(8, sizeof(type)); }\
(name).data = vec_temp;\
}
#define vec_set(vec, index, value, type) (*( ( (type*) (vec).data ) + (index) ) ) = value;
#define vec_get(vec, index, type) (*( ( (type*) (vec).data ) + (index) ) )
int main()
{
vec_new(p, int);
vec_set(p,0,5,int);
int g = vec_get(p, 0, int);
printf("%d",g);
return 0;
}

passing function pointer in c with a pointer argument

Here, I have defined two function pointers func1 and func2, and I guess this a way to use function pointers in c.But my question is when I call
executor(func1);
executor(func2);
How can I allocate memory for uint8_t * and pass it as an argument for either func1 and func2, so that I can use it back in main()
typedef int (*FUNC_PTR)(uint64_t, uint8_t*);
void executor(FUNC_PTR func)
{
uint64_t opts = 0x0000010;
uint8_t val = 0;
res = func(opts, &val);
}
int func1(uint64_t a, uint8_t* b)
{
//do some stuff
}
int func2(uint64_t a, uint8_t* b)
{
//do some stuff
}
void main()
{
executor(func1);
executor(func2);
}
Just add it to the argument list of executor.
void executor(FUNC_PTR func, uint8_t* b)
{
uint64_t opts = 0x0000010;
res = func(opts, b);
}
You can allocate the memory on the stack or heap in main.
void main()
{
uint8_t mem1, mem2;
executor(func1, &mem1);
executor(func2, &mem2);
}

Function overloading in C without using _Generic

I wish to accomplish function overloading in C, but I am attempting to run my code on a Unix server that does not have C11 support therefore the _Generic keyword is not available.
(Upgrading the server so it has a newer version of GCC is not an option).
Are there any alternatives to using _Generic to simulate effective function overloading in C?
You can do a limited form of overloading, for some argument types, like so:
void func_int(int);
void func_long(long);
void func_longlong(long long);
#define FUNC(X) \
(sizeof(X) <= sizeof(int) ? func_int(X) \
: sizeof(X) == sizeof(long) ? func_long(X) \
: func_longlong(X))
This will allow you to use FUNC(i) and have it call different functions. It's limited, because you can only distinguish types by their size. That means if sizeof(int) == sizeof(long) then you will never call func_long, and if sizeof(long) == sizeof(long long) then you will never call func_longlong. Also, you can't overload for other types, such as double, if sizeof(double) is the same as one of the integer types you're testing for.
It can be used to overload for e.g. float, double or long double, where you might have different implementations of a function that calculate more or less precisely depending on the precision (i.e. number of bits) in the argument type.
The GCC manual explicitly shows a GNU99 (-std=gnu99) workaround since at least version 3.1.1.
There are limitations, of course: all variants must have the same return type, and all function variants must make syntactic sense. The latter is often the cause of various compile errors (invalid types for function variant parameters). That can be avoided by declaring the functions without parameter prototypes; however, one must then remember that default type promotions will then take place (float are promoted to double, and all integer types smaller than int are promoted to int or unsigned int). Consider this example program:
#define _GNU_SOURCE /* for asprintf() */
#include <stdlib.h>
#include <stdio.h>
typedef struct {
double x;
double y;
double z;
double d;
} plane;
static const char *foo_char_array();
static const char *foo_int();
static const char *foo_long();
static const char *foo_double();
static const char *foo_float();
static const char *foo_short();
static const char *foo_plane();
#define foo(x) \
( __builtin_choose_expr( __builtin_types_compatible_p(typeof(x), int), foo_int(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), long), foo_long(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), short), foo_short(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), float), foo_float(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), double), foo_double(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), plane), foo_plane(x), \
__builtin_choose_expr( __builtin_types_compatible_p(typeof(x), char []), foo_char_array(x), \
(void)0 ))))))) )
int main(void)
{
double d = 1.0;
float f = 2.0f;
short s = 3;
long n = 4L;
plane p = { 5.0, 6.0, 7.0, 8.0 };
printf("foo(9) = %s\n", foo(9));
printf("foo(10L) = %s\n", foo(10L));
printf("foo(11.0f) = %s\n", foo(11.0f));
printf("foo(12.0) = %s\n", foo(12.0));
printf("foo(\"bar\") = %s\n", foo("bar"));
printf("foo(d) = %s\n", foo(d));
printf("foo(f) = %s\n", foo(f));
printf("foo(s) = %s\n", foo(s));
printf("foo(n) = %s\n", foo(n));
printf("foo(p) = %s\n", foo(p));
return EXIT_SUCCESS;
}
static const char *foo_char_array(char x[]) { return "char []"; }
static const char *foo_int(int x) { static char buffer[40]; snprintf(buffer, sizeof buffer, "(int)%d", x); return (const char *)buffer; }
static const char *foo_long(long x) { static char buffer[40]; snprintf(buffer, sizeof buffer, "(long)%ld", x); return (const char *)buffer; }
static const char *foo_float(double x) { static char buffer[40]; snprintf(buffer, sizeof buffer, "%af", x); return (const char *)buffer; }
static const char *foo_double(double x) { static char buffer[40]; snprintf(buffer, sizeof buffer, "%a", x); return (const char *)buffer; }
static const char *foo_short(int x) { static char buffer[40]; snprintf(buffer, sizeof buffer, "(short)%d", x); return (const char *)buffer; }
static const char *foo_plane(plane p) { static char buffer[120]; snprintf(buffer, sizeof buffer, "(plane){ .x=%g, .y=%g, .z=%g, .d=%g }", p.x, p.y, p.z, p.d); return (const char *)buffer; }
You do not need to determine the type based on a single parameter; you can do e.g. __builtin_types_compatible_p(typeof(x), double) && __builtin_types_compatible_p(typeof(y), double) to verify both x and y are of type double.
When compiled and run, the above program will output
foo(9) = (int)9
foo(10L) = (long)10
foo(11.0f) = 0x1.6p+3f
foo(12.0) = 0x1.8p+3
foo("bar") = char []
foo(d) = 0x1p+0
foo(f) = 0x1p+1f
foo(s) = (short)3
foo(n) = (long)4
foo(p) = (plane){ .x=5, .y=6, .z=7, .d=8 }
tested on 32-bit x86 Linux (ILP32), as well as on x86-64 (LP64). And yes, the above program will leak memory, since it never free()s the dynamically allocated strings returned by the foo_..() function variants.
I found a method that appears to work, however I still get a couple warnings at compile time...
Working code:
#include <stdio.h>
#define print(x) \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int(x) , \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string(x), \
(void)0))
void print_int(int i) {
printf("int: %d\n", i);
}
void print_string(char* s) {
printf("char*: %s\n", s);
}
int main(int argc, char* argv[]) {
print(1);
print("this");
return 0;
}
output:
int: 1
char*: thing
Compiler warnings:
gcc overload.c -o main
overload.c: In function 'main':
overload.c:19: warning: passing argument 1 of 'print_string' makes pointer from integer without a cast
overload.c:20: warning: passing argument 1 of 'print_int' makes integer from pointer without a cast
It is somehow possible using function pointers, and nameless struct inside a union. Here comes an example in which we overload the add and mul functions. There are two unions LIBI, and LIBF containing nameless structures. LIBI contains the function pointers add and mulc which only use integer values. LIBF is the same as LIBI except that add and mul use float variables. In addition, we need to create addi, muli, addf, and mulf functions outside of these unions. Functions pointers in unions will be referred to these 4 functions. For example, add in LIBI is referred to addi because addi uses int values and add in LIBF is referred to addf as it uses only float variables. This example can also be used as a way of emulating namespace in C which is absent in the language. Unions act like the namespace in this example.
#include<stdio.h>
#include<stdlib.h>
union {
struct {
void (*add)(int *, int);
void (*mul)(int *, int);
};
}LIBI;
union {
struct {
void (*add)(float *, float);
void (*mul)(float *, float);
};
}LIBF;
void addi(int *a, int c){
*a += c;
}
void addf(float *a, float c){
*a += c;
}
void muli(int *a, int c){
*a *= c;
}
void mulf(float *a, float c){
*a *= c;
}
int main(void){
LIBI.add = addi;
LIBF.add = addf;
LIBI.mul = muli;
LIBF.mul = mulf;
int ia = 10;
int ib = 2;
float fa = 20.0f;
float fb = 2.0f;
LIBI.add(&ia,ib);
LIBF.add(&fa,fb);
printf("%d\n",ia);
printf("%f\n",fa);
LIBI.mul(&ia,ib);
LIBF.mul(&fa,fb);
printf("%d\n",ia);
printf("%f\n",fa);
return 0;
}

how to pass enum value into structure

My problem is I need to pass value from argument (instType, typ1, *op1...) to the structure type tInst.
I'm sure it's a trivial problem but I've spent about 3 hours of my time working on it.
GCC returns segmentation fault 11.
my .h file
typedef enum tInstCode {
I_ADD=0, // (dest, addr, addr) +
I_SUB, // (dest, addr, addr) -
I_MUL, // (dest, addr, addr) *
I_DIV, // (dest, addr, addr) /
} tInstCode;
typedef enum TypeI{
INT=0,
DOUBLE,
STRING
} TypeI;
typedef struct iOperand
{
TypeI type;
void *content;
} iOperand;
typedef struct tInst
{
tInstCode instType;
iOperand *op1;
iOperand *op2;
iOperand *res;
} tInst;
typedef struct ListItem
{
tInst Instruction;
struct ListItem *NextItem;
} tListItem;
my main file :
void generateInstruction(tInstCode instType, TypeI typ1, void *op1, TypeI typ2, void *op2, TypeI typ3, iOperand *op3 )
{
tListOfInstr list;
listInit(&list); //list defined in another file
tInst* I;
I->instType = instType;
I->op1->type = typ1;
I->op1->content = op1;
I->op2 -> type = typ2;
I->op2 -> content = op2;
I->res -> type = typ3;
I->res -> content = op3;
listInsertLast(&list, *I);
}
int main(int argc, char** argv)
{
int a;
a=8;
int *b;
b = &a;
int c;
c=1;
int *d;
d = &c;
generateInstruction(0, DOUBLE, *b, INT, *d, INT, NULL);
}
tInst* I;
I->instType = instType;
You're not allocating memory for I.
As it currently is I is just a pointer with a (potentially) random value. Use malloc to get a suitable address with free memory.
This could be done like this:
tInst* I;
I = malloc(sizeof(tInst));
I->op1 = malloc(sizeof(iOperand));
I->op2 = malloc(sizeof(iOperand));
I->res = malloc(sizeof(iOperand));
Though keep in mind that malloc can fail, so you want to check the return value for NULL.

Resources