I have been given a .o file which creates a box_t ** and I have to use it.
Now, I don't know if it is
case 1:
an pointer to an array of box_t or
case 2:
an pointer to an array of box_t *
I wrote a simple code myself in creating box_t** in both the ways and accessed differently. It seems to be working fine in both the cases.
Now, given a box_t **, and size_t n, number of elements in it, is it possible to know if it is case 1 or case 2 without any further information.
struct box_tag{
int pencils;
int pens;
};
typedef struct box_tag box_t;
box_t boxarray[10] = {{1,2},{3,4},
{5,6},{7,8},
{9,10},{11,12},
{13,14},{15,16},
{17,18},{19,20}};
box_t ** box_bundle;
Creation Version1:
box_t** create_dp(void)
{
box_bundle = (box_t **)malloc(sizeof(box_t **));
*box_bundle = boxarray;
}
Accessing Version 1:
int main ()
{
box_t * tmp = *box_bundle;
for (int i =0; i<10; i++)
{
printf("%d\n",tmp[i].pencils);
}
return 0;
}
Creation Version 2:
box_t** create_dp (void)
{
box_bundle = (box_t **)malloc(sizeof(box_t **));
*box_bundle = (box_t *)malloc (sizeof(box_t *) * 10);
for(int i=0; i<10;i++)
{
*(box_bundle +i ) = &boxarray[i];
}
}
Accessing Version 2:
int main ()
{
create_dp();
for(int i=0; i<10; i++)
{
box_t * tmp =*box_bundle++;
printf("pencils %d \n", tmp->pencils);
}
return 0;
}
Both cases are incorrect. You can't use a box_t** to point at any array. Nor can it point to an array of type box_t boxarray[10], because they are incompatible types. There is no need for several levels of indirection anywhere in your code.
You can however use a box_t* to point at the first element in an array, and that's what your code does here: *box_bundle = boxarray;. But in an obfuscated way.
Correct code should be: box_t* box_bundle;. If it should point at the original array, there is no need for malloc. If it should hold a copy of the original array, you need to alloc and copy the data:
box_t* box_bundle = malloc (sizeof(*box_bundle)*10);
memcpy(box_bundle, boxarray, sizeof boxarray);
Related
The following code works fine without the statement d = *dummy; which is a double pointer dereference. However if this line is present, a segmentation fault occurs. Why so?
The code allocates and initializes memory for data structs dynamically. I was trying to simplify access to the returned pointer-to-pointer.
#include <stdlib.h>
#include <stdio.h>
typedef struct s_dummy {
char dummy_number;
} Dummy;
int mock_read_from_external_source() {
return 4;
}
int load_dummies(Dummy** dummies, int* num_of_dummies) {
*num_of_dummies = mock_read_from_external_source();
*dummies = (Dummy*) calloc(*num_of_dummies, sizeof(Dummy));
if (!dummies) {
return 1; // allocation unsuccessful
}
// Iterate dummies and assign their values...
for (int i = 0; i < *num_of_dummies; i++) {
(*dummies + i)->dummy_number = i;
}
return 0;
}
void main() {
Dummy** dummies;
Dummy* d;
int num_of_dummies = 0;
int *p_num_of_dummies = &num_of_dummies;
int err;
err = load_dummies(dummies, p_num_of_dummies);
// Segmentation fault occurs when dummies is dereferenced
d = *dummies;
if (err) {
exit(err);
}
for (int i = 0; i < num_of_dummies; i++) {
printf("Dummy number: %d\n", (*dummies + i)->dummy_number);
}
}
Thanks in advance.
You are getting the fault because of UB, in part caused by trying to use variable objects without memory. dummies, although created as a Dummies **, has never been provided memory. At the very least, your compiler should have warned you about dummies not being initialized in this call:
err = load_dummies(dummies, p_num_of_dummies);
This is easily addressed by simply initializing the variable when it is created:
Dummy** dummies = {0}; //this initialization eliminates compile time warnings
^^^^^
Then come the run-time errors. The first is called a fatal run-time on my system, which means the OS refused to continue because of a serious problem, in this case an attempt to dereference a null pointer in this line:
dummies = (Dummy) calloc(*num_of_dummies, sizeof(Dummy));
Because you created a Dummy ** called dummies, the first step is to create memory for the pointer to pointers dummies, then create memory for the several instances of dummies[i] that will result. Only then can the members of any of them be written to.
Here is one method illustrating how memory can be created for a Dummies pointer to pointers, ( d ) and several Dummies instances ( d[i] ):
Dummy ** loadDummies(int numPointers, int numDummiesPerPointer)
{
int i;
Dummy **d = {0};
d = malloc(numPointers * sizeof(Dummy *));//Create Dummies **
if(!d) return NULL;
for(i=0;i<numPointers;i++)
{ //Now create Dummies *
d[i] = malloc(numDummiesPerPointer*sizeof(Dummy)); //random size for illustration
if(!d[i]) return NULL;
}
return d;
}
In your main function, which by the way should really be prototyped at a minimum as: int main(void){...}, this version of loadDummies could be called like this:
...
Dummies **dummies = loadDummies(4, 80);
if(!dummies) return -1;//ensure allocation of memory worked before using `dummies`.
...
After using this collection of dummies, be sure to free all of them in the reverse order they were created. Free all instances of dummies[0]-dummies[numPointers-1] first, then free the pointer to pointers, dummies
void freeDummies(Dummy **d, int numPointers)
{
int i;
for(i=0;i<numPointers;i++)
{
if(d[i]) free(d[i]);
}
if(d) free(d);
}
Called like this:
freeDummies(dummies, 4);
dummies was never assigned a value, so de-referencing will attempt to reach some random memory which is almost certainly not going to be part of your program's allocated memory. You should have assigned it to &d.
But you don't even need to do that. Just use &d once when you call the function.
Also, if you return the number of dummies allocated instead of 1/0, you can simplify your code. Something like the below (not tested):
#include <stdio.h>
int mock_read_from_external_source() {
return 10;
}
typedef struct Dummy {
int dummy_number;
} Dummy;
int load_dummies(Dummy** dummies) {
int want, i = 0;
if((want = mock_read_from_external_source()) > 0) {
*dummies = (Dummy*) calloc(want, sizeof(Dummy));
if(*dummies) {
// Iterate dummies and assign their values...
for (i = 0; i < want; i++) {
(*dummies)[i].dummy_number = i;
}
}
}
return i;
}
int main() {
Dummy* d = NULL;
int num_of_dummies = load_dummies(&d); // when &d is de-referenced, changes are reflected in d
if(num_of_dummies > 0) {
for (int i = 0; i < num_of_dummies; i++) {
printf("Dummy number: %d\n", d[i].dummy_number);
}
}
if(d) { // clean up
free(d);
}
return 0;
}
I'm doing a school assignment, I've I've run into 2 problems. I have to simulate stacks, with arrays.
My current code is as follows:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int capacity;
int * array;
int size;
} stack_tt;
int pop(stack_tt * stack_p);
void push(stack_tt * stack_p, int value);
int top(stack_tt * stack_p);
stack_tt * newStack(void);
int empty(stack_tt * stack_p);
int main() {
stack_tt * myStack = newStack();
push(myStack, 123);
push(myStack, 99);
push(myStack, 4444);
while (!empty(myStack)) {
int value;
value = pop(myStack);
printf("popped: %d\n", value);
}
return 0; }
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt) * 20);
(*newS).capacity = 1;
(*newS).size = 0;
return newS;
}
void push(stack_tt * stack_p, int value){
if ((*stack_p).size >= (*stack_p).capacity) {
(*stack_p).capacity*=2;
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
}
(*stack_p).array = &value;
(*stack_p).size++;
}
int pop(stack_tt * stack_p){
(*stack_p).size--;
int fap = *(*stack_p).array;
return fap;
}
int empty(stack_tt * stack_p){
if ((*stack_p).size >= 1)
return 0;
return 1;
}
Fist of, when I call the line
while(!empty(myStack))
It changes the value in my array to 1.
secondly I'm not able to change individual values in my array, whenever I try things like:
(*stack_p).array[0] = value;
It doesn't know where in the memory to look.
I hope someone is able to help me out :)
There are a couple of problems with the code as I see it.
Lets take the push function where you do
(*stack_p).array = &value;
That will make the array structure member point to the local variable value, and once the function returns the variable cease to exist leaving you with a stray pointer and using that pointer will lead to undefined behavior.
The second problem with that code is that your stack will only be pointing (illegally) to the last element added.
You must allocate memory explicitly for array and use capacity to keep track of how much memory is allocated. The use size as an index into the allocated array for the pushing and popping. Something like
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt)); // Only allocate *one* structure
newS->capacity = 0; // Start with zero capacity
newS->size = 0;
newS->array = NULL;
return newS;
}
void push(stack_tt * stack_p, int value){
if (stack_p->size + 1 > stack_p->capacity){
// Increase capacity by ten elements
int new_capacity = stack_p->capacity + 10;
int * temp_array = realloc(stack_p->array, new_capacity * sizeof(int));
if (temp_srray == NULL)
return;
stack_p->capacity = new_capacity;
stack_p->array = temp_array;
}
stack_p->array[stack_p->size++] = value;
}
int pop(stack_tt * stack_p){
if (stack_p->size > 0)
return stack_p->array[--stack_p->size];
return 0;
}
int empty(stack_tt * stack_p){
return stack_p->size == 0;
}
There is no need to allocate space for 20 structs of type stack_tt, you only need to allocate space for one:
stack_tt * newS = malloc(sizeof(stack_tt));
however you need to allocate space for elements of the struct member array:
newS->array = malloc( sizeof(int)*20);
newS->size = 0;
newS->capacity = 20;
now you can use the array member.
When you push a value to the 'stack', you shouldn't overwrite the array member with the address of the local variable, that doesn't make sense and will cause undefined behavior in addition of loosing the previously allocated memory. Instead simply assign the value to the member array, in the function push:
stack_p->array[stack_p->size] = value;
stack_p->size++;
Similarly when you pop an element, take the current element from the member array:
stack_p->size--;
int fap = stack_p->array[stack_p->size];
The rest of the functions and code should be fixed in the same manner.
You're code is good, but probably you didn't understand the usage of realloc:
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
This function returns a pointer to the newly allocated memory, or NULL if the request fails.
The realloc (as the function suggests) takes the memory pointed by the pointer you pass, and copies that memory block in a new and resized block. So the right code should be.
stack_p->array = realloc(stack_p->array, stack_p->capacity * sizeof(stack_tt));
This other line is wrong:
(*stack_p).array = &value;
Change it with:
stack_p->array[stack_p->size] = value;
Another little suggestion, every (*stack_p). can be replaced by stack_p->, which is more elegant.
In the newStack() you're mallocing 20 structs which is kinda useless. You just need one.
Then you should malloc the array for the first time:
newS->array = malloc(sizeof(int));
newS->capacity = 1;
I'm trying to create an array of pointers in C. Each value of the array should be a pointer to a struct (let's call it struct Type*).
Should i do
struct Type* myVariable= malloc(sizeof(struct Type*)*MY_SIZE);
or
struct Type** myVariable= malloc(sizeof(struct Type*)*MY_SIZE);
The second one looks like what i should do when i want to create a two dimensional array, which are an array of pointer, and those pointers are used to create arrays of the wanted type.
EDIT : But in my case the second dimension size would be only one
The first one looks like a regular array with int* as the contained values type.
How can i pass the good solution to a function (by pointer, not by value because the array may be fairly large) and use it in the fonction ?
The second one the right solution. However, you'll need to allocate memory for the objects too. Also, make sure to check the value returned by malloc.
// Allocate memory for the array of pointers.
struct Type** myVariable = malloc(sizeof(struct Type*)*MY_SIZE);
if ( myVariable == NULL )
{
// Deal with error
exit(1);
}
for (int i = 0; i < MY_SIZE; ++i )
{
// Allocate memory for the array of objects.
myVariable[i] = malloc(sizeof(struct Type)*THE_SIZE_IN_THE_OTHER_DIMENSION);
if ( myVariable[i] == NULL )
{
// Free everything that was allocated so far
for (int j = 0; j < i-1; ++j )
{
free(myVariable[j]);
}
free(myVariable);
// Exit the program.
exit(1);
}
}
However, if THE_SIZE_IN_THE_OTHER_DIMENSION is going to be 1, you are better off using your first approach.
struct Type* myVariable = malloc(sizeof(struct Type)*MY_SIZE);
// ^^^^^^^^^^^ Drop the *
if ( myVariable == NULL )
{
// Deal with error
exit(1);
}
Neither!
Use an idiom that reduces work and errors
pointer = malloc(sizeof *pointer * Number_of_elements);
Or in OP's case "to create an array of pointers in C"
#define ARRAY_N 100
struct Type **myVariable = malloc(sizeof *myVariable * N);
if (myVariable == NULL) Handle_OutOfMemmory();
Now set those pointers to some value
#define M 50
size_t i;
for (i=0; i<N; i++) {
myVariable[i] = malloc(sizeof *(myVariable[i]) * M);
if (myVariable[i] == NULL) Handle_OutOfMemmory();
for (size_t m = 0; m<M; m++) {
// Initialize the fields of
myVariable[i][m].start = 0;
myVariable[i][m].value = 0.0;
myVariable[i][m].set = NULL;
}
}
I have a queue of set length implemented as a dynamic c array implemented like this:
typedef struct {
float* queue;
int size;
int pointer;
} QueueStruct;
void createQueue(QueueStruct* queueInstance, int size){
queueInstance->queue = malloc(sizeof(float)*size);
queueInstance->size = size;
queueInstance->pointer = 0;
}
void addElementToQueue(QueueStruct* queueInstance,float element){
queueInstance->queue[pointer] = element;
if (queueInstance->pointer == queueInstance.size - 1){
queueInstance->pointer = 0;
} else {
++queueInstance->pointer;
}
}
void freeQueue(QueueStruct* queueInstance){
free(queueInstance->queue);
}
And I want to implement this function:
float* returnQueue(QueueStruct queueInstance){
//I want this function to malloc a new float* and then put the queue in it in the
// correct order, from start to finish, as pointed too by the pointer.
//Im not sure how to do this.
}
Any help would be appreciated.
Edit: Corrected a silly programming mistake - this is a simplified version of what is actually in my program.
Let's see if I got that right.
float* returnQueue(QueueStruct *queueInstance){
int j = 0;
float *ret = malloc(sizeof(float)*queueInstance->size); //Allocates the memory you want.
//Copies the elements from pointer to End into the new buffer (assumes, that the array has been filled at least once, add a marker to make sure)
if(queueInstance->FilledOnce) { //Marker variable, explanation as above.
for(int i = queueInstance->pointer; i < queueInstance->size; ++i, ++j)
ret[j] = queueInstance->queue[i];
}
//Copies the newest elements (from beginning to pointer) into the buffer.
for(int i = 0; i < queueInstance->pointer; ++i, ++j)
ret[j] = queueInstance->queue[i];
return ret; //Returns the code in question.
}
To make this code work, you'd have to add 'FilledOnce' to your struct, and amend your 'Add' Code as follows:
void addElementToQueue(QueueStruct* queueInstance, float element){
queueInstance->queue[queueInstance->pointer] = element;
if (queueInstance->pointer == queueInstance.size - 1){
queueInstance->pointer = 0;
queueInstance->FilledOnce = 1;
} else {
++queueInstance->pointer;
}
}
I also advise you, to reset your variables, once you're done with it.
void freeQueue(QueueStruct* queueInstance){
free(queueInstance->queue); //Frees the queue
queueInstance->queue = NULL; //Nulls the reference
queueInstance->FilledOnce = 0;
queueInstance->pointer = 0;
queueInstance->size = 0;
}
This way, if you reuse the struct, you won't run into the problem of trying to access non-allocated memory. Just be sure to check for those variables.
I hope this helps.
I think you should allocate memory for your struct also.
You have made pointer of struct but forgot to allocate memory for that struct
use QueueStruct queuestruct= malloc(sizeof(Queuestruct))
then when you pass this to any of the function above then you can easily allocate
memory for queue poiter in which you can store element for your queue array
This implementation is insufficient. A pointer variable give us location of a tail of queue, but what points to it's head?
I'm working on some project where I use the type mpz_t from the GMP C library. I have some problems passing an array of structures (containing mpz_ts) adress to a function :
I wille try to explain my problem with some code.
So here is the structure :
struct mpz_t2{
mpz_t a;
mpz_t b;
};
typedef struct mpz_t2 *mpz_t2;
void
mpz_t2_init(mpz_t2 *mpz_t2)
{
mpz_init(mpz_t2->a);
mpz_init(mpz_t2->b);
}
void
petit_test(mpz_t2 *test[])
{
printf("entering petit test function\n");
for (int i=0; i < 4; i++)
{
gmp_printf("test[%d]->a = %Zd and test[%d]->b = %Zd\n", test[i]->a, test[i]->b);
}
}
/* IN MAIN FUNCTION */
mpz_t2 *test = malloc(4 * sizeof(mpz_t2 *));
for (int i=0; i < 4; i++)
{
mpz_t2_init(&test[i]); // if I pass test[i] : compiler error
mpz_set_ui(test[i].a, i); //if test[i]->a compiler error
mpz_set_ui(test[i].b, i*10); //same problem
gmp_printf("%Zd\n", test[i].b); //prints correct result
}
petit_test(test);
The programm prints the expected result (in main) but after entering the petit_test function produces a segmentation fault error.
I would need to edit the mpz_t2 structure array in petit_test.
I tried some other ways allocating and passing the array to the function but I didn't manage to get this right.
If someone has a solution to this problem, I would be very thankfull!
Regards,
jérôme.
In the code that you have displayed, you are allocating memory for the array of pointers, but you are not initializing the pointers to point to anything. You need to allocate some instances of mpz_t2, and then assign your pointers to point to them.
---------------edited here---------------
It looks like this is what you're trying to do:
mpz_t2 **test = (mpz_t2**)malloc(4 * sizeof(mpz_t2 *));
for (int i=0; i < 4; i++)
{
test[i] = (mpz_t2*)malloc(sizeof(mpz_t2));
mpz_t2_init(test[i]);
...
}
petit_test(test);