Initializing a pointer to a structure through a void function in C - c

Let my structures be:
typedef struct{
double x;
double y;
} punt;
typedef struct{
char tip;
punt infEsq
punt supDret;
} rectangle;
typedef struct{
rectangle *llista;
int numRect;
int midaMax;
} taulaRectangle;
Contextualizing,
"Punt" represents a point.
"Rectangle", char indicates if it's a square [q] or a rectangle [r], the two points are the inferior left point (infEsq) and the superior right point (supDret) of the rectangle.
"TaulaRectangle" maps a list (or table) of structures type "rectangle", indicating how many rectangles it has [numRect], and how many it can hold [midaMax] (which if I am not wrong indicates the dimension of [llista]).
Now I want to code a function to initialize a pointer to "taulaRectangle" like this:
void initaula(taulaRectangle *t,int n) /*n is associated to midaMax*/
I will not post my intents in coding a valid initialization function because I believe they're not close to what I want to achieve although here is a similar scenario where I did try something alike:
void inipunt(punt *b){
b->x=0;
b->y=1;
return;
}
int main (void){
double b,n;
punt *a;
inipunt(a);
puts("guay");
a.x=b;
a.y=n;
printf("a.x=%lf a.y=%lf",b,n); /*I know this association is not necessary
but if I directly print a.x a.y it does
not work either, also a fail is *(a.x),*
(a.y) */
return 0;
}
The compiler (gcc -ansi -Wall) returns:
final1.c:30:2: error: request for member ‘x’ in something not a
structure or union a.x=b; ^ final1.c:31:2: error: request for
member ‘y’ in something not a structure or union a.y=n; ^
Synthesizing, I want to be able to declare a pointer to "taulaRectangle" and initialize it using "void initaula()", I typed the example above because I believe what I want to achieve in both functions is similar except in "void inipunt()" I do not have to allocate memory for a pointer in the structure, I think the problem has it's roots in how i treat the pointer to the structure in my void function.
Sorry for the long question, if anyone can help It will be gladly appreciated.

As Eugene pointed out in the comments, the pointer is not allocated.
When you do punt *a;, you're only allocating a pointer to the structure, but it doesn't point to anything yet. It's not initialized.
Keep your uninitialized variables in check, as they could have any value. You have no idea what an uninitialized pointer could be pointing to.
You have two solutions for this problem:
Allocate space for the structure in the stack, by doing punt a;. In this case a is the struct.
Allocate space for the structure in the heap, by doing punt *a = malloc(sizeof(punt)). In this case a is a pointer to the struct.
If you allocate the space in the stack, to get the pointer for a, you should do &a.
Keep in mind that to access a struct behind a pointer, you use -> instead of ..
This should work:
void inipunt(punt *p) {
p->x = 0;
p->y = 1;
}
int main() {
punt a;
inipunt(&a);
printf("%lf %lf\n", a.x, a.y);
punt *b = malloc(sizeof(punt)); // You should check if it returns NULL, in case of an error.
inipunt(b);
printf("%lf %lf\n", b->x, b->y);
return 0;
}

Related

Access value from a pointer to a pointer

I am trying to access a field from a struct through a pointer of pointer
I tried:
(**vform).vpolygon->point->x = 1;
But doesn't worked.
code:
typedef struct point{
int x;
}point;
typedef struct polygon{
point *point;
}polygon;
typedef struct form{
polygon **polygon;
}form;
void main(){
polygon *vpolygon;
form **vform;
vpolygon = (polygon *)malloc(sizeof(polygon)*5);
vform = (form **)malloc(sizeof(form)*5);
vpolygon->point->x = 1;
vform->vpolygon->point->x = 1;
}
I expect the program compile, but the actual output is
18:12: error: '*vform' is a pointer; did you mean to use '->'?
vform->vpolygon->point->x = 1;
^~
->
The code below should compile in what you seem to want. There are however a lot of issues with what you're doing that may not be immediately obvious, but I'll go into that a little below.
typedef struct point {
int x;
} point;
typedef struct polygon {
// dynamically allocated array of point
point *point;
} polygon;
typedef struct form {
// dynamically allocated array of polygon
polygon *polygon;
} form;
form *vform;
vform = malloc(sizeof(form) * 5);
vform->polygon = malloc(sizeof(polygon) * 5);
vform->polygon->point = malloc(sizeof(point) * 5);
vform->polygon->point->x = 1;
First issue is that you're mixing up your variables with the members of your structures. Your form structure has no element called "vpolygon". Just because your "vpolygon" variable is a polygon structure doesn't mean you can suddenly refer to the polygon member of a form variable by calling it "vpolygon".
Secondly, you're casting the return value of malloc. Don't do this. See do I cast the result of malloc
Thirdly, your form malloc is allocationing enough memory for 5 form structures, but casting the result to a pointer to a pointer to form. The malloc should possibly be malloc(sizeof(form *) * 5) but I'm guessing you really meant (vform *)malloc... not (vform **)malloc....
Fourth, you're dynamically allocating arrays and pointing your variables at the first element in the array but you don't seem to have any mechanism to detect the size of the array. You need a method to track the size of the array so you don't accidentally cause a segmentation fault by going off the end of the array. (Three common methods: 1) track the number of elements allocated. 2) Mark the end of the array with some marker value and check for if, 3) hard-code it. All have trade-offs)
Fifth. You want to store the original value returned by malloc so you can free it at some point - if you modify what vfrom points to you'll lose that original address and cause memory leaks.

Limitations in "struct inside struct"

There are 2 struct definitions A and A. I know that there is OK to struct A contain a POINTER to struct A but I don't understand why struct A cannot contains struct A (not a pointer)
Because when you put structs inside each other, you're putting another copy of that struct into the struct at that point. For example:
struct A {
int q;
int w;
};
struct B {
int x;
struct A y;
int z;
};
This will be laid out in memory like this:
int /*B.*/x;
int /*A.*/q;
int /*A.*/w;
int /*B.*/z;
But if you try to put a struct inside itself:
struct A {
int x;
struct A y;
};
you have an A, which contains an int and another A, which contains an int and another A, and now you have an infinite number of ints.
Because in that case, it will take infinite storage as it will have to recursively store the data member of its own type. So, it is not possible. Whereas, Size of a pointer is fixed and hence causes no problem.
Let's suppose it could contain an object of its own type:
struct A_
{
A_ a;
int b;
} A;
What's sizeof(A) ? Answer: sizeof(A)+sizeof(int): impossible.
Because the structure definition is not finished until the closing curly-brace }. To declare a structure member the compiler need the full definition, as it uses that information to calculate things like space and padding and alignment etc. For a pointer to something the size of the pointer is the size of the pointer, and all the compiler needs os the name of the type, not its full definition.
Lets take a simple structure for example:
struct A // Here the compiler knows that there is a structure named A
// The compiler does not know its contents, nor its size
{
// Some members...
struct A *pointer_to_a; // All the compiler needs to know is the symbol A
// The size and alignment is that of a pointer
// and those are known by the compiler
// Some more members...
// struct A instance_of_A; // This is not possible! At this point the
// compiler doesn't have the full definition
// of the structure, and can therefore not
// know how much space it need to allocate
// for the member
// Some even more members...
}
// Now the compiler knows the full contents of the structure, its size
// and alignment requirements
;

Compiler warnings and notes but dropping & does not work

In the below code snippet I'm getting a gcc compiler warning: "passing argument 1 of initArr from incompatible pointer type initArr(&stack,2);"
and a note: "expected 'struct Arr *' but argument is of type 'struct Arr**'"
which makes perfect sense to me.
As suggested by many a SO post, dropping the ampersand from the call to initArr(&stack, 2) however, results in another warning: "'stack' is used unitialized in this function: init(stack, 2);" and an immediate segfault error when ran.
What am I doing incorrectly?
I also tried using struct Arr in the malloc sizeof call and as expected, no change.
#include<stdio.h>
#include <stdlib.h>
#define TYPE int
struct Arr {
TYPE * data; // Pointer to the data array.
int size; // Number of elements in the array.
int capacity; // Capacity of the array.
};
void initArr(struct Arr * da, int capacity) {
da->data = malloc(sizeof(TYPE) * capacity);
da->size = 0;
da->capacity = capacity;
}
int main() {
struct Arr *stack;
initArr(&stack, 2);
return 0;
}
As haccks answer says,
you need to initialize your pointer, so it points to a real location
pass the pointer (rather than the address of the pointer variable)
int main()
{
struct Arr realArray; // allocate memory for the Arr (on the CPU's stack)
struct Arr *stack; // pointer variable (undefined)
stack = &realArray; // make variable "stack" point to realArray
initArr(stack, 2); // pass the pointer to realArray
}
stack is a pointer and it must be pointing to some valid memory location. Since stack is passed to the function and isn't initialized, you are getting a warning. In the function you are trying to access some random memory location which can cause the program crash or any erroneous behavior of the program, aka undefined behavior.
Change this:
struct Arr *stack;
To this:
struct Arr stack;
First look at the declaration of your initArr function:
void initArr(struct Arr * da, int capacity)
Your first argument is of type 'pointer to a struct'
Now look at your invocation of this function:
struct Arr *stack;
initArr(&stack, 2);
We see that stack is of type 'pointer to a struct', and in the function you are passing the address of stack (.i.e. the type is a pointer to a pointer to a struct). Which is what the gcc error is about, the note actually gives more information about the type that the function expects and the type that you are providing
There are two ways to fix this
leave the declaration of initArr as it is, and then change the function
invocation from initArr(&stack, 2) to initArr(stack, 2). In this case you will need to make sure that you have allocated memory for the structure prior to passing it to the function;
int main()
{
struct Arr* da = NULL;
da = malloc(sizeof(struct Arr));
initArr(da, 2);
}
or equivalently,
int main
{
struct Arr stack;
initArr(&stack, 2);
}
I would probably go for one of the above solutions.
Modify the declaration of initArr to initArray(struct Arr** da, int capacity). You will still need to make sure memory is allocated as before. However, if you change initArr to:
void initArr(struct Arr** da, int capacity)
{
*da = malloc(sizeof(struct Arr));
(*da)->data = malloc(sizeof(TYPE) * capacity);
(*da)->size = 0;
(*da)->capacity = capacity;
}
In this case I am changing the semantics of your initArr function so that I am initializing the structure all in one place. The code in your main function would remain unchanged.
N.B. For clarity, error checking has been omitted in the above code snippets, please don't do this in real code. Always check the return value from malloc to ensure that memory has been allocated.

ansi-c - assign array value in structure

I need help assigning a value to an array with in a structure. Your help is greatly appreciated:
typedef struct _temp_t {
int16_t _values[4];
} TEMP_T;
void func() {
TEMP_T *temps;
int x = 5;
temps._values[0] = x;
}
I'm getting an error :
...src/rodm/ucdCom.c:512: error: request for member '_values' in something not a structure or union
Your help is greatly appreciated!
TEMP_T *temps;
temps is a pointer, so it has no members, only structs and unions have members.
After you allocated memory for temps, you could set
temps->_values[0] = x;
Or you can declare temps as a TEMP_T,
TEMP_T temps;
and leave the rest of the code as is.
TEMP_T *temps;
Drop the * from that line. Then it will be a true TEMP_T object instead of a pointer.
Alternatively, malloc some memory to temps and then use:
temps->_values[0] = x;
The OP didn't have any sign of an allocated struct TEMPT_T anywhere.
He had a pointer, but nothing for it to point to. His code then attempts an assignment with member access syntax (temps._values[0];), as opposed to pointer access syntax (temps->_values[0];).
A slightly better version of his code might look like:
typedef struct _temp_t {
int16_t _values[4];
} TEMP_T;
void func(struct TEMPT_T in) {
TEMP_T *temps = &in;
int x = 5;
temps->_values[0] = x;
}
The function's new definition implies that a struct TEMP_T must exist for it to be used, and thus the pointer access into the structure becomes legal.

Accessing members in a pointer to a pointer of a struct

Code is as follows:
/* set.h */
struct setElement{
char *element;
setElement *next;
};
typedef struct setElement *Set; //Set is now the equivalent of setElement*
Set a;
setInit(&a);
/* setInit function declaration # setInit.c */
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Trying to malloc 'a' works, but if I try to access any member within the set 'a' doesn't work. I understand I'm passing a reference of the set from the main() function to setInit, so I believe the pointer contained within setInit is addressing the memory allocated by 'Set a' in the main() function, so a malloc wouldn't be required...
Iunno. Help is appreciated :)
The problem is that you have not allocated the setElement you are trying to assign to. In the main part of the code you are creating a Set, which is just a pointer to a setElement. This pointer is never set to point to anything sensible. I.e. you need something like
Set a = malloc(sizeof(setElement));
Alas, it is unclear where exactly your variables are defined. I assume your main.c is something like
#include "set.h"
Set a;
int main()
{
setInit(&a);
}
If so, your a, which is a pointer by itself, should point to somewhere.
If your framework wants malloc()ed data, you should do
int main()
{
a = malloc(sizeof(*a)); // *a is a struct setElement now, with 2 pointer-sized members.
setInit(&a); // Now seInit should be able to operate on the struct as wanted.
}
As #amaurea has mentioned, you'll need to make use of malloc() for your setElement structure. In addition to this, you need to do the same for the setElement struct's element member. A char* is merely a pointer to a char or char array and will not implicitly allocate anything.
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Could be re-written
int setInit(Set *a){
(*a)->element = malloc(sizeof("asdf"));
strcpy((*a)->element,"asdf");
}
Which the above could be rewritten to take a second parameter of the actual element contents.

Resources