Pass pointer to struct by reference in C - c

Take in mind the following piece of code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A* a)
{
a->a = 3;
a->b = 2;
a->c = 1;
}
int main()
{
test = malloc(sizeof(A));
init(test);
printf("%d\n", test->a);
return 0;
}
It runs fine! Now imagine that I want to use the malloc function outside the main itself without returning a pointer to the struct. I would put malloc inside init and pass test adress. But this doesnt seem to work.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
*a->a = 3;
*a->b = 2;
*a->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}
It keeps telling me that int a(or b/c) is not a member of the struct A when I use the pointer.

Your problem is operator precedence. The -> operator has higher precedence than the * (dereference) operator, so *a->a is read as if it is *(a->a). Change *a->a to (*a)->a:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}

You must add parenthesis:
void init(A **a)
{
*a = malloc(sizeof(A)); // bad you don't verify the return of malloc
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
But it's good practice to do this:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
ret->a = 3;
ret->b = 2;
ret->c = 1;
}
*a = ret;
}

You need to write (*a)->a = 3; for reasons of precedence.

Even though it's not a direct answer to your question, since we're in the vicinity of initialization I'd like to point out that C11 gives you a nicer syntax to initialize structs:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
*ret = (A) {3, 2, 1};
// or
*ret = (A) { .a = 3, .b = 2, .c = 1 };
}
*a = ret;
}
Another advantage is that any uninitialized members are zeroed.

Related

Why when I try to access array of structures it returns random values? (C)

I have a function that returns pointer to array of structures. However, when I try to access any of the values of returned structure, it prints random symbols.
#include <stdio.h>
struct MY {
int i;
char string[30];
};
struct MY* myFunc() {
struct MY arrayOfStructs[3];
struct MY tempStruct;
struct MY* arrayOfStructsPtr = arrayOfStructs;
tempStruct.i = 1;
tempStruct.string[0] = 'H';
tempStruct.string[1] = 'i';
arrayOfStructs[0] = tempStruct;
tempStruct.i = 2;
tempStruct.string[0] = 'L';
tempStruct.string[1] = 'o';
arrayOfStructs[1] = tempStruct;
tempStruct.i = 3;
tempStruct.string[0] = 'M';
tempStruct.string[1] = 'Y';
arrayOfStructs[2] = tempStruct;
return arrayOfStructsPtr;
}
int main()
{
struct MY* arrayOfStructs = myFunc();
for(int i = 0; i < 3; i++) printf("%d\n", arrayOfStructs[i].i);
return 0;
}
You return a reference to the local array which stops to exist when function returns. It is Undefined Behaviour.
You need:
struct MY* myFunc(void) {
static struct MY arrayOfStructs[3];
or
struct MY* myFunc(void) {
struct MY *arrayOfStructs = malloc(3 * sizeof(*arrayOfStructs));
or pass the buffer allocated by the caller.
struct MY *myFunc(struct MY *arrayOfStructs) {
/* .... */
If you dynamically allocate memory you should free it after use
You return a pointer to a local variable which is out of scope when the function returns. Some alternatives:
The caller main() allocates variable and pass it to myFunc() for initialization.
#include <stdio.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
void myFunc(struct MY arrayOfStructs[N]) {
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < N; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
}
int main() {
struct MY arrayOfStructs[N];
myFunc(arrayOfStructs);
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
}
As used here you don't really need to store i as it's just index of the struct + 1.
myFunc() dynamically allocate the variables with malloc() and return the pointer. Caller is responsible for free'ing the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
struct MY *myFunc() {
struct MY *arrayOfStructs = malloc(N * sizeof *arrayOfStructs);
if(!arrayOfStructs) return NULL; // malloc failed
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < sizeof strings / sizeof *strings; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
return arrayOfStructs;
}
int main() {
struct MY *arrayOfStructs = myFunc();
if(!arrayOfStructs) return 1;
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
free(arrayOfStructs);
}
myFunc(): make variables static (not recommended).

How to refer to a specific struct in an array, while the array is in a struct in a function in C?

the program is run: ./program objekty
objekty - name of file without .txt
Here is the problem which should be as minimal as possible:
(I'm trying to get both printfs on stdout)
#include <stdio.h>
#include <stdlib.h>
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
void obj_ctor(struct obj_t *p, struct obj_t obj){
p->id = obj.id;
p->x = obj.x;
p->y = obj.y;
}
void pass(struct cluster_t *p, struct obj_t add){
obj_ctor(&p->obj[0],add);
p->size += 1;
}
void pass1(struct cluster_t **arr){
struct obj_t o3;
o3.id = 1; o3.x = 2; o3.y = 3;
int count = 20;
int pos = 0;
while(pos < 3){
arr[pos]->capacity = 3;
arr[pos]->size = 0;
arr[pos]->obj = malloc(count*sizeof(struct obj_t));
pass(arr[pos], o3);
pos++;
}
}
int main(int argc, char *argv[])
{
printf("Testing");
struct cluster_t *test;
pass1(&test);
printf("GOT HERE");
}
The final minimal example is nicely manageable — thank you. Here is a fairly straight-forward extension of that code. It is lazy in that it uses assert() to enforce necessary properties.
It includes a function to dump the data in a struct cluster_t structure. I regard such functions as a necessity — at the very least, they're extremely helpful. Quite often, I write them to take a FILE *fp argument so that messages can be written to standard output, standard error or to a log file, or, indeed, anywhere you can point a file stream. Often, I'd have a separate dump_obj() function that would be invoked from dump_cluster(), but it doesn't seem necessary here.
The key point is that it ensures that test.obj in main() points to an array of 3 struct obj_t. If you want dynamic memory allocation, changes are needed.
/* SO 7467-2430 */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
struct obj_t
{
int id;
float x;
float y;
};
struct cluster_t
{
int size;
int capacity;
struct obj_t *obj;
};
static void obj_ctor(struct obj_t *p, struct obj_t obj)
{
p->id = obj.id;
p->x = obj.x;
p->y = obj.y;
}
static void pass(struct cluster_t *p, struct obj_t add)
{
assert(p != NULL && p->obj != NULL);
assert(p->size < p->capacity);
obj_ctor(&p->obj[p->size], add);
p->size += 1;
}
static void dump_cluster(const char *tag, struct cluster_t *p)
{
printf("%s (%p):\n", tag, p);
if (p != NULL)
{
printf("size = %d, capacity = %d, objects = %p\n", p->size, p->capacity, p->obj);
for (int i = 0; i < p->size; i++)
printf(" [%d] id = %d, pos = (%g, %g)\n", i, p->obj[i].id, p->obj[i].x, p->obj[i].y);
}
}
int main(void)
{
printf("Testing\n");
struct cluster_t test;
struct obj_t o1, o2, o3;
o1.id = 1;
o2.id = 2;
o3.id = 3;
o1.x = 1;
o2.x = 2;
o3.x = 3;
o1.y = 1;
o2.y = 2;
o3.y = 3;
test.capacity = 3;
test.size = 0;
struct obj_t arr[3];
test.obj = arr;
pass(&test, o3);
printf("GOT HERE\n");
dump_cluster("After adding 1", &test);
pass(&test, o2);
pass(&test, o1);
dump_cluster("After adding 3", &test);
return 0;
}
Example output (the addresses will probably differ for you):
Testing
GOT HERE
After adding 1 (0x7ffeed15b3b0):
size = 1, capacity = 3, objects = 0x7ffeed15b3c0
[0] id = 3, pos = (3, 3)
After adding 3 (0x7ffeed15b3b0):
size = 3, capacity = 3, objects = 0x7ffeed15b3c0
[0] id = 3, pos = (3, 3)
[1] id = 2, pos = (2, 2)
[2] id = 1, pos = (1, 1)

invalid use of incomplete typedef in C

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;
};

C iterate array by known sizeof

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.

Access struct member by an argument of function in C

int f(){
struct NUMBER {
int A;
int B;
};
struct NUMBER *num = malloc(sizeof(struct NUMBER));
num->A = 1;
num->B = 2;
int x = num->B;
return x;
}
int main(){
int z = f();
printf("%d\n", z);
}
Obviously, ./a.out will show 2.
My question: Can I access struct member by an argument of function? i.e. f(A) return 1, and f(B) return 2. Thanks a lot.
Not at all elegant, but I think it shows you what you need to do/know.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
struct NUMBER {
int A;
int B;
};
struct NUMBER extNumber = {1, 2};
int f(int offset) {
int iRet = -1;
if (offset == offsetof(struct NUMBER, A)) {
iRet = extNumber.A;
} else if (offset == offsetof(struct NUMBER, B)) {
iRet = extNumber.B;
}
return iRet;
}
int main (int argc, char **argv) {
struct NUMBER number;
int iVal;
iVal = f(offsetof(struct NUMBER, A));
printf ("A : %d\n", iVal);
iVal = f(offsetof(struct NUMBER, B));
printf ("B : %d\n", iVal);
}
Can I access struct member by an argument of function?
I think you are also assuming struct is not visible outside the function. Now if the person who wrote main does not have visibility into the function (say it is part of a library), then the answer is NO.
Otherwise if author of main can see internals of the function, then: Can someone come up with a fancy way to access struct member inside the function via function argument? Towards that lets think what does f(A) mean? Here, A is a name of struct member, so do you mean passing char A to f and translating that to struct member inside f [e.g. result = *(int *)num+(inchar-'A') where inchar is aninput parameter to the function of type char]. Similarly, one can imagine other ways.
As far as I understand your problem, the cleanest and most "C-like" solution is to pass a pointer to your struct to f(), where you populate it:
typedef struct _NUMBER
{
int A;
int B;
}
NUMBER;
void f (NUMBER* pvNumber)
{
pvNumber->A = 1;
pvNumber->B = 2;
return;
}
Call it like this:
int main ()
{
NUMBER vNumber;
int z;
f (&vNumber);
z = vNumber.A; // or vNumber.B
return 0;
}
So you don't select the desired member inside f(), but outside of it.
Yes. you need to define some way to access to member desired, this is usually done with constants, or an enum. As an aside, you should always check the pointer returned by malloc() before using it.
#define GET_A (0)
#define GET_B (1)
int f(int selector){
struct NUMBER {
int A;
int B;
};
int result;
struct NUMBER *num = malloc(sizeof(struct NUMBER));
if (!num)
return -1; // or some other error code...
num -> A = 1;
num -> B = 2;
switch(selector)
{
case GET_A: result = num->A; break;
case GET_B: result = num->B; break;
// etc... if you have more members in your struct.
default: result = -1; break; // some error code.
}
free(num)
return result;
}
int main(){
int z = f(GET_B);
printf( "%d\n" , f(GET_B));
}

Resources