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;
}
Related
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);
}
While trying to pass an argument to a function; the function receives the wrong value thus creating a segmentation fault while trying to use that value
argc and argv in the main function are corrupted before the program even starts
main.c file:
#include <stdio.h>
#include <stdlib.h>
#include "util/BasicTypes.h"
#include "util/IncludeOpengl.h"
#include "util/Vec2.h"
#include "util/Vec3.h"
#include "util/Vec4.h"
#include "util/Vector.h"
#if !(defined(__linux__) || defined(_WIN64))
STATIC_ASSERT(false, unsupported_system)
#endif
i32 main(i32 argc, ch8** argv) {
//u32 a[] = {1, 2, 3, 4};
//u32* b = a;
u32 i;
Vector v;
init_Vector(&v, sizeof(u32));
for (i = 0; i < 4; i++) {
printf("%i\n", i);
Vector_append(&v, &i);
}
for (i = 0; i < Vector_getSize(&v); i++) {
printf("%i\n", Vector_get(&v, i));
}
destruct_Vector(&v);
return 0;
}
vector.c file where i define the vector functions:
#ifndef VECTOR_C
#define VECTOR_C
#include "../util/Vector.h"
#include "../util/BasicTypes.h"
#include "../util/Assert.h"
void init_Vector(Vector* self, u32 elementSize) {
self->elementSize = elementSize;
self->elements = NULL;
self->elementCount = 0;
}
void destruct_Vector(Vector* self) {
if (self->elements) {
heapFree(self->elements);
}
}
void Vector_append(Vector* self, void* element) {
if (self->elements) {
self->elements = heapRealloc(self->elements, self->elementCount + 1);
memcpy(((byte*)self->elements) + (self->elementCount) * self->elementSize, element, self->elementSize);
self->elementCount += 1;
return;
}
else {
self->elements = heapAlloc((usize)self->elementSize);
memcpy(self->elements, element, self->elementSize);
self->elementCount += 1;
return;
}
}
void Vector_remove(Vector* self, u32 id) {
if (id < self->elementCount) {
void* temp = self->elements;
self->elements = heapAlloc((self->elementCount - 1) * self->elementSize);
memcpy(self->elements, temp, id * self->elementSize);
memcpy(((byte*)self->elements) + id * self->elementSize, ((byte*)temp) + (id + 1) * self->elementSize, (self->elementCount - id - 1) * self->elementSize);
self->elementCount -= 1;
}
else {
ASSERT(false, "(Vector_remove) id is not in the list");
}
}
void Vector_insert(Vector* self, void* element, u32 id) {
if (!self->elements && !id) {
self->elements = heapAlloc(self->elementSize);
self->elementCount = 1;
}
else {
if (id < self->elementCount + 1) {
void* temp = self->elements;
self->elements = heapAlloc((self->elementCount - 1) * self->elementSize);
memcpy(self->elements, temp, id * self->elementSize);
memcpy(((byte*)self->elements) + (id + 1) * self->elementSize, ((byte*)temp) + (id) * self->elementSize, (self->elementCount - id - 1) * self->elementSize);
memcpy(((byte*)self->elements), ((byte*)temp), self->elementSize);
self->elementCount += 1;
}
else {
ASSERT(false, "(Vector_insert) id is too far");
}
}
}
void* Vector_get(Vector* self, u32 id) {
return ((byte*)self->elements) + id * self->elementSize;
}
u32 Vector_getSize(Vector* self) {
return self->elementCount;
}
#endif // VECTOR_C
vector.h file the header file for vector.c:
#ifndef VECTOR_H
#define VECTOR_H
#include "../util/BasicTypes.h"
typedef struct Vector {
void* elements;
u32 elementSize;
u32 elementCount;
} Vector;
void init_Vector(Vector* self, u32 elementSize);
void destruct_Vector(Vector* self);
void Vector_append(Vector* self, void* element);
void Vector_remove(Vector* self, u32 id);
void Vector_insert(Vector* self, void* element, u32 id);
void* Vector_get(Vector* self, u32 id);
u32 Vector_getSize(Vector* self);
#endif // VECTOR_H
basictypes.h file where i define some aliases:
#ifndef BASIC_TYPES_H
#define BASIC_TYPES_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef i8 ch8;
typedef i16 ch16;
typedef i32 ch32;
typedef i64 ch64;
typedef u8 uch8;
typedef u16 uch16;
typedef u32 uch32;
typedef u64 uch64;
typedef float f32;
typedef double f64;
typedef long double f128;
typedef u8 byte;
typedef size_t usize;
#endif // BASIC_TYPES_H
typedef i8 ch8; is wrong, since int8_t might likely expand to signed char, which in turn is not directly compatible with char unless you explicitly covert between the two types.
The format of main is not for the programmer to decide, but the compiler. gcc under strict compliance settings (-pedantic-errors) tells you this much:
error: second argument of 'main' should be 'char **' [-Wmain]
Besides, nobody wants to read code based on your own special type system. We have standards for a reason, so use standard C instead:
#include <stdint.h>
....
int main (int argc, char* argv[])
{
uint32_t i;
I'm implementing a data structure in C and I get this error in my test file. Without adding code because then that would be a huge post with a ton of code to go through, but here's what my code looks like:
header.h file:
typedef struct array Arr;
functions.c file:
#include "header.h"
struct array{
int number;
int size;
char *names;
}
main.c file:
#include "header.h"
bool function(const Arr *const variable)
{
for (int i = 0; i < variable->size; i++)
{
variable->number[i] = i;
}
}
and so I get the error mentioned in the title referring to Arr*->number and Arr->*size. What I suspect to be the issue is that Arr is only typedefed but not defined. If that's the case, how can I resolve it?
Here's the main code:
main.c
#include <stdio.h>
#include "header.h"
int main(){
set *setA = set_empty();
set_insert(69,setA );
set_insert(15, setA);
set *setB = set_empty();
set_insert(12,setB );
set_insert(15, setB);
set *setDiff = set_difference(setA, setB);
printf("\n");
print_set(setDiff);
bool diff = verify_difference(setDiff, setA, setB);
}
bool verify_difference(const set *const setDiff, const set *const setA, const struct set *const setB)
{
bool answer = true;
for (int x = 0; x < setDiff->size; x++)
{
if (set_member_of(setDiff->array[x], setA) && set_member_of(setDiff->array[x], setB))
{
answer = false;
break;
}
}
return answer;
}
header.h
#ifndef HEADER_H
#define HEADER_H
#include <stdbool.h>
typedef struct set set;
set *set_empty();
void set_insert(const int value, set *s);
bool set_member_of(const int value, const set *const s);
functions.c
#include <stdio.h>
#include "header.h"
struct set {
int capacity;
int size;
char *array;
};
set *set_empty()
{
struct set *ptr = malloc(sizeof(struct set));
ptr->size = 0;
ptr->array = malloc(sizeof(char));
ptr->capacity = 1;
return ptr;
}
void set_insert(const int value, set *s)
{
if (!set_member_of(value, s)) {
int bit_in_array = value; // To make the code easier to read
// Increase the capacity if necessary
if (bit_in_array >= s->capacity) {
int no_of_bytes = bit_in_array / 8 + 1;
s->array = realloc(s->array, no_of_bytes);
for (int i = s->capacity / 8 ; i < no_of_bytes ; i++) {
s->array[i] = 0;
}
s->capacity = no_of_bytes * 8;
}
// Set the bit
int byte_no = bit_in_array / 8;
int bit = 7 - bit_in_array % 8;
s->array[byte_no] = s->array[byte_no] | 1 << bit;
s->size++;
}
}
set *set_difference(const set *const s1, const set *const s2)
{
struct set *s = set_empty();
for (int i = 0; i < s1->size; i++)
{
if (!set_member_of(s1->array[i], s2))
{
set_insert(s1->array[i], s);
}
}
for (int i = 0; i < s2->size; i++)
{
if (!set_member_of(s2->array[i], s1))
{
set_insert(s2->array[i], s);
}
}
return s;
}
bool set_member_of(const int value, const set *const s)
{
int bit_in_array = value;
if (bit_in_array >= s->capacity) {
return false;
}
int byte_no = bit_in_array / 8;
int bit = 7 - bit_in_array % 8;
char the_byte = s->array[byte_no];
return the_byte & 1 << bit;
}
The definition of the structure shall be available in main. Otherwise the compiler does not know whether there is the data member number in the structure referred in this statement
Arr->number[i] = i;
Moreover in any case this statement is incorrect because Arr is a type specifier and according to the structure definition the data member number is not an array
It seems you mean
variable[i].number = i;
But as the function parameter
bool function(const Arr *const variable)
is declared as a pointer to a constant object then you may not change pointed to data members of the structure.
So either move the definition of the function function from main.c in functions.c or place the structure definition in the header file.
And there is a typo
Typedef struct array Arr;
^^T
you need to use lower case letter
typedef struct array Arr;
I can only hazard a guess. Your code snippet could be wrong.
Move the structure definition to header.h & check.
//header.h file:
typedef struct array Arr;
struct array{
int number;
int size;
char *names;
};
I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.
I am just working on a liberty functions in which we define our own datatypes for student and book I have to write a code which finds student by id and book by id these are the two functions. In this functions the pointers which I pass are different but the logic is the same so I got a though that why can't we write one function and pass which thing we want. I mean when we pass the student list it will return the index of student when we pass the book list it will return the book index of the book. Can we use void pointers for that??? Thank you everyone!!!
int findBookId(Book* booklist,int* bcount,unsigned int* tbid)
{
int i;
for (i=0; i<*bcount; i++)
{
if (booklist[i].id==*tbid)
{
return i;
}
}
return NOT_FOUND;
}
int findStuId(Student* stulist,int* scount,unsigned int* tsid)
{
int i;
for (i=0; i<*scount; i++)
{
if (stulist[i].id==*tsid)
{
return i;
}
}
return NOT_FOUND;
}
Assuming you have a student structure:
struct student {
int id;
char name[20];
};
You can imitate qsort() function, to design a parameter to receive a callback function and to receive the size and size of each element if you'd like use void *.
int find_ele(void *base, size_t num, size_t width,
int (*equal)(const void *, const void *),
void *param)
{
int i;
for (i = 0; i < num; ++i) {
if (equal((char *) base + i * width, param)) {
return i;
}
}
return -1;
}
Then, define a "tester":
int student_tester(const void *p1, const void *p2)
{
struct student *sp = (struct student *) p1;
int id = *(int *) p2;
return sp->id == id;
}
In main() function:
int main(void)
{
struct student student_list[] = {
0, "A",
1, "B",
2, "C"
};
int id = 2;
int index = find_ele(student_list, sizeof student_list,
sizeof(struct student), student_tester, &id);
if (index != -1) {
printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
index, student_list[index].name);
} else {
printf("Not found. \n");
}
return 0;
}
This is a bit complicated. You can create macros to simplify it if you don't care.
Rename find_ele to _find_ele, and create a macro:
#define find_ele(base, num, compare, param) _find_ele(base, \
num / sizeof base[0], \
sizeof base[0], \
compare, param)
And create another macro to define a "tester":
#define define_tester(name, type, type_to_find, code) \
int name(const void *_p, const void *param) { \
type *p = (type *) _p; \
type_to_find value = *(type_to_find *) param; \
return (code); \
}
Now you can define a "tester" like this:
define_tester(student_tester, struct student, int,
p->id == value);
Complete code:
#include <stdio.h>
int _find_ele(void *base, size_t num, size_t width,
int (*equal)(const void *, const void *),
void *param)
{
int i;
for (i = 0; i < num; ++i) {
if (equal((char *) base + i * width, param)) {
return i;
}
}
return -1;
}
#define find_ele(base, num, compare, param) _find_ele(base, \
num / sizeof base[0], \
sizeof base[0], \
compare, param)
#define define_tester(name, type, type_to_find, code) \
int name(const void *_p, const void *param) { \
type *p = (type *) _p; \
type_to_find value = *(type_to_find *) param; \
return (code); \
}
struct student {
int id;
char name[20];
};
define_tester(student_tester, struct student, int,
p->id == value);
int main(void)
{
struct student student_list[] = {
0, "A",
1, "B",
2, "C"
};
int id = 2;
int index = find_ele(student_list, sizeof student_list, student_tester, &id);
if (index != -1) {
printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
index, student_list[index].name);
} else {
printf("Not found. \n");
}
return 0;
}
Yes you can use void*, but while dereferencing you should know the exact type of the pointer.
So, when you can your function, add another parameter:
type = 0 for Books
= 1 for students
And then your function becomes:
int findId(void* list,int* count,unsigned int* tbid, int type)
{
Book* booklist=NULL;
Student* stulist=NULL;
int i;
if(type===0)
booklist = (Book*) list;
else if(type==1)
stulist = (Student*) list;
else
// Handle this undefined case
// And now use the same type variable to decide which pointer to use to match the values
. . . .
}
Yes you can use void pointer, if you are trying to store address of your array..Your array may contain integer types or some other datatypes stored, it doesn't matter, but right typecasting while de-referencing the void pointer is important.
I don't think you can use void* in these functions.
If you changed your functions to one and created something like:
int findObjId(void* objlist,int* count, unsigned int* objid)
{
int i;
for (i=0; i<*scount; i++)
{
if (objlist[i].id==*objid)
{
return i;
}
}
return NOT_FOUND;
}
you won't be able to extract the data from objlist. Neither *objlist, nor objlist[i] can be dereferenced to evaluate to an object. The compiler will definitely stop you from using any such statement.
If you have the option, switch to C++. Using templates, you can accomplish your goal without breaking a sweat.