When allocating memory for a pointer to a record I also need space for an integer pointer located just before the allocated record. This pointer cannot be part of the record itself and it cannot be placed after the record. My current approach is the following:
#include <stdlib.h>
static int n;
struct { int f; } *p;
p = malloc(sizeof (int *) + sizeof *p);
if (p != NULL) {
p = (void *) ((int **) p + 1);
*((int **) p - 1) = &n;
}
Are the casts well defined? If not, what should I do instead?
Edit:
What I'm trying to achieve is to implement extensible records (OOP) and the integer pointer represent a type ID. An extended record should be compatible with its base type. However, I only need type ID:s for pointer to records. Here is a complete example:
#include <assert.h>
#include <stdlib.h>
struct T0 {
int f;
};
int T0ID;
struct T1 {
struct T0 base;
int g;
};
int T1ID;
int main(void)
{
struct T0 *x;
struct T1 *y;
y = malloc(sizeof (int *) + sizeof *y);
if (y != NULL) {
*((int **) y) = &T1ID;
y = (void *) ((int **) y + 1);
((struct T0 *) y)->f = 1;
y->g = 2;
}
x = (struct T0 *) y;
assert(x->f == 1);
return 0;
}
I'm not sure your approach is good. Especially I'm worried about changing the value of p. You'll need that value later when you need to free the memory.
I would wrap the int* and the struct together in another struct. Something like:
static int n;
struct someData { int f; };
struct wrapper {int* pn; struct someData data;};
struct someData* pd; // Pointer to the data struct
struct wrapper* pw = malloc(sizeof *pw);
if (pw != NULL) {
pw->pn = &n;
pd = &pw->data;
}
Your code, in which you cast (arbitrary) memory addresses to particular object types, is might yield undefined behaviour due to incorrect alignment (cf.
C standard draft):
6.3.2.3 Pointers
(7) A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined.
You are having a pointer declared to be of type struct{int}* pointing to a (larger memory block), and then casting the pointer and doing arithmetic operations on the (casted) pointer. As it is not guaranteed that int * and struct{int}* are aligned the same way, it is not guaranteed that the behaviour is defined.
To avoid this, encapsulate your structure and the preceeding integer in another structure, e.g. as follows:
static int n;
struct data_struct {
int f;
};
struct enclosing_struct {
int *nPtr;
struct data_struct data;
};
int main() {
struct enclosing_struct *e = malloc (sizeof(struct enclosing_struct));
e->nPtr = &n;
struct data_struct *dataPtr = &e->data;
return 0;
}
Related
I was wondering if I have a code like this:
struct something{
int x;
float y;
};
int main(void)
{
struct something *p;
p = malloc(sizeof(struct something));
p->x = 2;
p->y = 5.6;
return 0;
}
what's the content of *p (with *) if called somewhere? Is it the address of the structure or what?
Here's an example of the usage of *p - that is, dereferencing the pointer:
#include <stdio.h>
#include <stdlib.h>
struct something {
int x;
float y;
};
int main(void) {
struct something *p;
p = malloc(sizeof *p);
p->x = 2;
p->y = 5.6;
struct something s;
s = *p; // dereference p and copy into s
free(p);
// now check s:
printf("%d, %.1f\n", s.x, s.y); // prints 2, 5.6
}
p is a pointer to struct something. *p will dereference that pointer to give the struct itself. But, here is the catch: struct (*p) is a composite data type, you need to use a . operator to get its member.
(*p).x = 2;
(*p).y = 5.6;
This can also be done without using the indirection operator (*) (as you did):
p->x = 2;
p->y = 5.6;
I have been struggling with the ideas behind malloc and realloc for quite some time now and at the moment I have a problem with dynamically creating an array of structs. I have a struct triangle which itself is composed of an array of struct coordinates. I would like to be able to have an array of triangles which is as large as necessary, but every time I attempt to increase the length of my array, nothing seems to happen. Realloc doesn't fail and neither does malloc. However the new triangles are not inserted in my array. Here is my code for reference.
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
triangles[size] = t;
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(triangles, t);
}
}
I have tried every variation of this I have found, but I would rather not just blindly throw in & and * until something happens.
As-is, your program invokes undefined behavior when it passes an uninitialized *triangles to realloc: https://taas.trust-in-soft.com/tsnippet/t/9ff94de4 . You probably meant to pass &triangles when you called it in main.
Changing the call in main to addTriangle(&triangles, t);, the next issue is an out-of-bounds access inside addTriangle: https://taas.trust-in-soft.com/tsnippet/t/658228a1 . Again this may be because you have the wrong level of indirection and meant something like (*triangles)[size]
instead of triangles[size].
If I change the line triangles[size] = t; to (*triangles)[size] = *t; then there is no undefined behavior. You should check whether this program still does what you want, since it was modified: https://taas.trust-in-soft.com/tsnippet/t/8915bd2d
The final version:
#include <string.h>
#include <stdlib.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
(*triangles)[size] = *t; // a struct assignment
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(&triangles, t); /* pass the address of triangles
so that addTriangle can modify this variable's contents */
}
}
Side remarks not directly related to the problem you asked about
As long as you program in C, please do not cast the result of malloc. Simply write struct triangle* triangles = malloc(....
As noted by #aschepler in the comments, this program still leaks the memory blocks allocated from main. These can be freed at the end of each iteration without adding any undefined behavior: https://taas.trust-in-soft.com/tsnippet/t/a0705262 . Doing this, you may realize that t->point[0] = *a;, ... are in fact struct assignments and that it was unnecessary to allocate a separate struct coordinate in the first place: you could just fill in each struct coordinate member of the struct triangle. In addition, it was unnecessary to allocate the struct triangle in main, too: you could just use a local variable for that, since anyway the contents of the struct will be copied by the function addTriangle to the array that main's local variable triangles points to.
Also you don't need to call free(triangles) if triangles is a null pointer in main:
struct triangle* triangles = (struct triangle *) malloc(...
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
It is allowed to pass a null pointer to free, and this does what you would expect (it does nothing), but since you know that triangles is NULL in the then branch, simply call exit.
Handling the failure of realloc on the other hand is a subtle subject. Your program is doing it wrong, but it does not really matter because it calls exit immediately.
Storing information about the allocated array pointed by main's local variable triangles in a static file-scope variable size is not consistent. The two are so closely related that they should be in the same scope. Since you need addTriangle to be able to change size, you cannot simply move size to be a local variable of main, but you can move the local variable triangles of main to file scope, next to size. If you prefer to make size a local variable of main after all, you will need to pass its address to the function addTriangle so that the latter can update the former.
Change the function call as
addTriangle(&triangles, t);
You can replace the whole body of your for loop with
struct triangle t = {{{i, 2*i},{3*i,4*i},{5*i,6*i}}};
addTriangle(&triangles, &t);
Please note the & before the parameters, because you want to pass the address of both.
I already noticed as a comment that triangles[size] = t; should be (*triangles)[size] = *t;
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
exit(EXIT_FAILURE);
}
*triangles = ts;
(*triangles)[size] = *t;
size++;
}
int main() {
struct triangle* triangles = malloc(sizeof(struct triangle));
if(triangles == NULL) {
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct triangle t = {{{i, 2*i},{3*i,4*i},{5*i,6*i}}};
addTriangle(&triangles, &t);
}
for(int i = 0; i < size; i++) {
printf("%d %d, %d %d, %d %d\n", triangles[i].point[0].x,
triangles[i].point[0].y,
triangles[i].point[1].x,
triangles[i].point[1].y,
triangles[i].point[2].x,
triangles[i].point[2].y);
}
}
i am created a struct
typedef struct t{
int top;
int value;
}s;
and another structure
typedef struct y{
int top1;
s **p
}z;
z *p1;
created a block by malloc
p1 = (z*) malloc(sizeof(z));
p1->p = (s**) malloc(10 * sizeof(s));
I tried with indexing the s structured block by
p1->p[4]->top;
but i got error. is there a way to index pointer to pointer type in C
Address them with single pointer.
typedef struct y{
int top1;
s *p; //Single pointer only
}z;
z *p1;
p1 = malloc(sizeof(z)); //Don't cast...
p1->p = malloc(10 * sizeof(s));
//And then:
p1->p[4].top;
If you still want double pointers, then:
typedef struct y{
int top1;
s **p;
} z;
z *p1;
size_t i;
p1 = malloc(sizeof(z)); //Create z structure object
p1->p = malloc(10 * sizeof(*p1->p)); //Create array of pointers to objects
//Now fill that array with your objects
for (i = 0; i < 10; i++) {
p1->p[i] = malloc(sizeof(*p1->p[i]));
}
//Now access to property as:
p1->p[4]->top; //Do something.
The second option is less preferable but depends on you, because doing single mallocfor 10 objects in a row is more efficient than doing 10x times single object and 11th time for initializing base array of pointers.
In struct y{ ...; s **p }, member p represents a pointer to a pointer to structure s, and not a pointer to structure s.
So p1->p[4] is a pointer to an s, not an s itself, so you cannot access member top with accessor .. To get around the compiler error, you would have to use accessor ->, which dereferences the pointer value, but then you yield undefined behaviour at runtime, since the pointer value is not initialized.
To solve the problem, you could either change the data type of p to s *p (as suggested by #tilz0R), or you could adapt your code to actually deal with pointers to pointers:
typedef struct t{
int top;
int value;
}s;
typedef struct y{
int top1;
s **p;
}z;
z *p1;
int main() {
p1 = malloc(sizeof(z));
p1->p = malloc(10 * sizeof(s*));
for (int i=0; i<10; i++) {
p1->p[i] = malloc(sizeof(s));
}
p1->p[4]->top = 5;
}
Note that pointers to pointers are more complicated to handle, as you need an extra step/loop to initialize the pointers and to free them later on. So actually I'd prefer the s *p-way; But sometimes pointers to pointers are more appropriate, e.g. if particular slots of the array shall remain "empty"; then you could set the respective pointer to NULL, which would not be possible in an array of struct objects.
I am having problems with this program. It's very simply. I need to assign values to my struct from the pointers I created, but I keep getting a segmentation fault. Any ideas what I'm doing wrong:
#include <stdio.h>
#include <stdlib.h>
struct problem37
{
int a;
int b;
int c;
};
int main()
{
printf("Problem 37\n");
//create struct
struct problem37 myStruct;
//create the pointer
int* p;
int* q;
int* r;
*p = 1;
*q = 5;
*r = 8;
//read the data into the struct using the pointers
myStruct.a = *p;
myStruct.b = *q;
myStruct.c = *r;
printf("%d\n", myStruct.a);
printf("%d\n", myStruct.b);
printf("%d\n", myStruct.c);
return 0;
}
Your are assigning a value to *p, *q and *r, but they are not initialized: they're pointers pointing to random memory.
You need to initialize them, either assigning them a new value allocated in the heap (with malloc):
int *p = (int*) malloc( sizeof(int) );
*p = 1;
or making them point to an already existent value:
int x;
int *p = &x;
*p = 1; // it's like doing x=1
Your problem is that you write at random memory locations since you do not initialize your pointers nor allocate memory.
You could do the following:
int* p = malloc(sizeof(int));
int* q = malloc(sizeof(int));
int* r = malloc(sizeof(int));
Obviously you need to free them when you are done using them:
free(p);
free(q);
free(r);
You're not allocating memory to the pointer. Therefore when you're doing *p and *q and *r you're dereferencing a null pointer (or a random pointer). This leads to a segmentation fault. Use p = malloc(sizeof(int)); when you declare the variables.
I'm trying to cast a struct into another struct but I'm having incompatible pointer issues within the cast and the malloc under some_func (structs layout are the same)
struct stu1 **some_func(struct stu1 *my_struct)
{
my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size);
for(i=0;i<20;i++){
my_struct[i] = (struct stu1 *)malloc(sizeof(struct stu1));
printf("%s",my_struct[i++]->a);
}
return my_struct;
}
int main()
{
struct stu1 **my_struct;
struct stu2 **my_struct2;
struct stu3 **my_struct3;
my_struct = some_func(my_struct);
my_struct2 = (struct stu2**)some_func((struct stu1*)my_struct2);
my_struct3 = (struct stu3**)some_func((struct stu1*)my_struct3);
}
Several problems.
Firstly, you have incompatible types all over the place. In the line
my_struct = some_func(my_struct);
my_struct has type struct stu1 **, but the definition of some_func expects a parameter of type struct stu1 *; the two types are not the same. A pointer to T is not the same type as a pointer to pointer to T.
Secondly, your casting gymnastics are not going to work as you expect. Pointer types are not automatically compatible; their base types must be compatible, and different struct types are not compatible, even if their layouts are the same, e.g.:
struct {int x, int y} foo;
struct {int x, int y} bar;
struct S {int x, int y} blurga;
struct S bletch;
foo, bar, and bletch are of different types and are not compatible, even though their layouts are the same. blurga and bletch are of the same type (struct S). If struct stu2 or struct stu3 have different sizes from struct stu1, then you won't allocate the right amount of memory for my_struct2 and my_struct3.
For the sake of clarity and your sanity, you should have different allocation functions for each type, rather than trying to force a square peg into a pentagonal hole:
struct stu1 **stu1_alloc(size_t count)
{
struct stu1 **arr = malloc(sizeof *arr * count);
if (arr)
{
size_t i;
for (i = 0; i < count; i++)
{
arr[i] = malloc(sizeof *arr[i]);
if (arr[i])
{
// initialize arr[i] as necessary
}
}
}
return arr;
}
struct stu2 **stu2_alloc(size_t count)
{
struct stu2 **arr = malloc(sizeof *arr * count);
if (arr)
{
size_t i;
for (i = 0; i < count; i++)
{
arr[i] = malloc(sizeof *arr[i]);
if (arr[i])
{
// initialize arr[i] as necessary
}
}
}
return arr;
}
struct stu3 **stu3_alloc(size_t count)
{
struct stu3 **arr = malloc(sizeof *arr * count);
if (arr)
{
size_t i;
for (i = 0; i < count; i++)
{
arr[i] = malloc(sizeof *arr[i]);
if (arr[i])
{
// initialize arr[i] as necessary
}
}
}
return arr;
}
int main(void)
{
struct stu1 **my_struct = stu1_alloc(SIZE);
struct stu2 **my_struct2 = stu2_alloc(SIZE2);
struct stu3 **my_struct3 = stu3_alloc(SIZE3);
...
}
Yes, the only thing different between the three allocation functions is the type. However, if the different struct types have different sizes or different initialization needs, then this is necessary.
Notice a couple of things. First of all, I'm not casting the result of malloc(). There are two reasons for this. One, as of C89 and later, you don't have to: malloc() returns a type of void *, which is implicitly converted to the target pointer type. Two, and more importantly, if I forget to include stdlib.h or otherwise don't have a prototype for malloc() in scope, leaving the cast off will trigger an "incompatible types" warning (since undeclared functions are assumed to return int, and you cannot implicitly convert an int value to a pointer type). If you cast the return value of malloc(), then you supress that warning and risk problems at runtime (since the value returned by malloc() will be converted from void * to int, and then from int to the target pointer type, which is not guaranteed to work).
Secondly, I'm using sizeof on the object, not the type. This has two benefits. One, the code is a little easier to read. Two, if I change the type of the object, I don't have to go back and change every call to malloc().
If you really don't want to have three separate allocation functions, you could try some macro magic like this:
#define ALLOC_STU(target, size) \
do { \
target = malloc(sizeof *target * size); \
if (target) \
{ \
size_t i; \
for (i = 0; i < size; i++) \
{ \
target[i] = malloc(sizeof *target[i]); \
} \
} \
} while(0)
int main(void)
{
struct stu1 **my_struct;
...
ALLOC_STU(my_struct, SIZE);
...
}
although I think the separate allocation functions are the safer way to go.
struct stu1 **some_func(struct stu1 *my_struct)
{
my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size);
my_struct is of type struct stu1 *, but you are trying to assign a (casted) struct stu1 **
Just guessing, do you want something like this:
struct stu1 **some_func(struct stu1 ***my_struct)
{
*my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size);
for(i=0;i<20;i++){
(*my_struct)[i] = (struct stu1 *)malloc(sizeof(struct stu1));
printf("%s",(*my_struct)[i++]->a);
}
return *my_struct;
}
int main()
{
struct stu1 **my_struct;
struct stu2 **my_struct2;
struct stu3 **my_struct3;
my_struct = some_func(&my_struct);
}
But this doesn't make much sense. The return value would not be necessary.
Where to begin ...
You must match your types. some_func() expects a single pointer; in one instance you are passing a double pointer (a pointer to a pointer).
Inside some_func(), the 1st malloc() has a type-mismatch. It is attempting to set a double pointer to a single pointer.
Inside some_func(), the 2nd malloc() is has another type-mismatch. It is attempting to set a non-pointer (the structure) to a pointer.
Inside some_func(), it appears as though you may be trying to dynamically a two-dimensional array. For reference, there are two ways to do this with malloc().
Method #1. (Without error checking)
struct stu1 **some_func(int dim1, int dim2)
{
struct stu1 **my_struct;
int i;
/* Allocate space for an array of <dim1> pointers */
my_struct = (struct stu1 **) malloc(sizeof(struct stu1 *) * dim1);
/* Allocate <dim2> elements for each pointer */
for (i = 0; i < dim1; i++){
my_struct[i] = (struct stu1 *) malloc (sizeof (struct stu1) * dim2);
}
return (my_struct);
}
Method #2. (Again, without error checking)
struct stu1 **some_func(int dim1, int dim2)
{
struct stu1 **my_struct;
int i;
char *data;
/* Allocate space for everything. */
data = (char *) malloc((sizeof (struct stu1 *) * dim1) + (dim1 * dim2 * sizeof (struct stu1)));
my_struct = (struct stu1 **) data;
/* Initialize pointers to pointers. */
data = (char *) &my_struct[dim1];
for (i = 0; i < dim1; i++) {
my_struct[i] = (struct stu1 *) data;
data += sizeof (struct stu1) * dim2;
}
return (my_struct);
}
Each method has its advantages and disadvantages. Hope this helps.