C structure struct pointer and functions - c

I have recently read a code but I have a doubt in code
toTs *now = try();
now->index = 30;
Where toTs is a struct and try() is a function with return type toTs*
*now being a pointer can keep address of label try() but as try() not being a structure variable now can't access it like struct and can never access it like now->index=30.
After compiling it shows segmentation fault.
I just want to ask is above code legitimate or not.
#include <stdio.h>
#include <unistd.h>
typedef struct toT {
int index;
} toTs;
toTs lst[3];
toTs *try() {
int i;
for (i = 0; i < 3; i++) {
toTs *current = &lst[i];
printf("%d\n", current->index);
if (current->index == 3) {
printf("test work");
return current;
}
}
}
int main() {
int i;
for (i = 0; i < 3; i++) {
lst[i].index = i;
}
for (i = 0; i < 3; i++) {
printf("test %d\n", lst[i].index);
}
toTs *now = try();
now->index = 30;
printf("current %d\n", now->index);
printf("current %d\n", lst[2].index);
}
now is a struct pointer that can point to struct variable but try() is not a struct variable nor array of data structure its a function

You need to always return a valid toTs* from try() for the code to work.
#include <stdio.h>
#include <unistd.h>
typedef struct toT {
int index;
} toTs;
toTs lst[4];
toTs *try() {
int i;
for (i = 0; i < 3; i++) {
toTs *current = &lst[i];
printf("%d\n", current->index);
if (current->index == 3) {
printf("test work");
return current;
}
}
return &lst[3]; // return a spare structure.
}
int main() {
int i;
for (i = 0; i < 3; i++) {
lst[i].index = i;
}
for (i = 0; i < 3; i++) {
printf("test %d\n", lst[i].index);
}
toTs *now = try();
now->index = 30;
printf("current %d\n", now->index);
for (i = 0; i < 4; i++) {
printf("Final %d\n", lst[i].index);
}
}
You're confusing function pointers with plain pointers in C. Function pointers go deeper : https://en.wikipedia.org/wiki/Function_pointer

This code is not particularly healthy.
Given the way lst is initialized, when you call try() it will reach the end of that function without a return statement.
The C Standard says that if you use the return value of a function, without actually returning a value, that's undefined behavior.

Related

How do u dynamically fill a struct *array instead of manually making them

we've been working on some structs, and decided that we wanted to make them dynamic so we could run a function that would basically make AREASIZE amount of struct areas and store them in our area *array, instead of us having to manually make a block of code with for example 10, 100 or 1000 struct areas and subsequently *Narea amount of subareas.
We've been stuck a couple of hours, and thought it might be more productive to ask where our logic is shit, cuz we cannot seem to find it. The code just crashes in the nested for loop of our create areas function.
Our logic:
we have a struct *array called area, which has a struct *array inside called subareas.
we pass the struct *array area to our function create_areas
create_areas uses the arrow operator to parse through our struct *array areas[i] and then our struct *array subareas[j]. And then fills up the values of our subareas.
before exiting we also assign the other value in our struct *array area, which is its average
In our heads would lead to our struct *array area being filled with 5x areas.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MARGIN 70
#define MARGIN2 30
#define SIZE 5
#define NAREA 4
#define AREASIZE 5
typedef struct subarea
{
int co2_cost, time;
double average, sensorData[SIZE];
} subarea;
typedef struct area
{
subarea *subarea_array[NAREA];
double average;
} area;
void create_areas(area *area_array[NAREA]);
void sensor_data_start(area *area, double start_var);
int main(void)
{
int co2_counter = 0, time_counter = 0;
int day_counter = 0;
int area_number;
srand(time(NULL));
area *area_array[AREASIZE] = {};
create_areas(area_array);
printf("Hello");
return 0;
}
void create_areas(area *area_array[NAREA])
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
printf("Second for loop\n");
area_array[i]->subarea_array[j]->co2_cost = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->time = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->average = 0;
printf("Second for loop\n");
sensor_data_start(area_array[i], 0);
}
area_array[i]->average = 0;
}
}
void sensor_data_start(area *area, double start_var)
{
for (int i = 0; i < NAREA; i++)
{
for (int j = 0; j < SIZE; j++)
{
area->subarea_array[i]->sensorData[j] = start_var;
}
}
}
This:
area *area_array[AREASIZE] = {};
Creates an array of pointers to areas (area *). You have yet to create any areas!.
Thus when you try to access area_array[i]->subarea_array you access unallocated memory, causing a crash.
Look into pointers in C if you don't understand why.
Look into the malloc and free functions to actually instantiate your areas. You will also need the sizeof operator.
Note: you will have to do the same with subareas.
In the end you're looking for something like this:
void create_areas(area *area_array[NAREA])
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
area_array[i] = malloc(sizeof(area)); //or malloc(sizeof(*area_array[i]))
if (area_array[i] == NULL) //always check malloc return value!!
exit(-1);
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
area_array[i]->subarea_array[j] = malloc(sizeof(subarea));
if (area_array[i]->subarea_array[j] == NULL) //always check malloc return value!!
exit(-1);
printf("Second for loop\n");
area_array[i]->subarea_array[j]->co2_cost = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->time = 0;
printf("Second for loop\n");
area_array[i]->subarea_array[j]->average = 0;
printf("Second for loop\n");
sensor_data_start(area_array[i], 0);
}
area_array[i]->average = 0;
}
}
Happy Learning!
Use pointer to structs which will act as array :
typedef struct subarea
{
int co2_cost, time;
double average, sensorData[SIZE];
// note that you can also define sensorSata as pointer and allocate dynamically
} subarea;
typedef struct area
{
subarea *subarea_array; // will be allocated dynamically
double average;
} area;
int main(void)
{
…
/*allocate soace for the area array */
area *area_array = calloc(AREASIZE, sizeof(area));
create_areas(area_array);
printf("Hello");
return 0;
}
void create_areas(area *area_array)
{
printf("create areas\n");
for (int i = 0; i < AREASIZE; i++)
{
/* allocate space for subarea */
area_array[i].subarea_array = malloc(sizeof(subarea)*NAREA);
printf("First for loop\n");
for (int j = 0; j < NAREA; j++)
{
printf("Second for loop\n");
area_array[i].subarea_array[j].co2_cost = 0;
printf("Second for loop\n");
area_array[i].subarea_array[j].time = 0;
printf("Second for loop\n");
area_array[i].subarea_array[j].average = 0;
printf("Sensor dafa start\n");
sensor_data_start(&area_array[i], 0);
}
area_array[i].average = 0;
}
}
void sensor_data_start(area *area, double start_var)
{
for (int i = 0; i < NAREA; i++)
{
// you can allocate sensorSata here if it was a pointer
for (int j = 0; j < SIZE; j++)
{
area->subarea_array[i].sensorData[j] = start_var;
}
}
}
Other things that could be done for more dynamic is to add the number of subarea in area struct if it is not constant . Same for sensorSata if you make it dynamic.

C, Segmentation fault while using dynamic array in struct

I'm trying to add new element to dynamic array in C (I know that I must free all memory. I will do it later), but I get this error every time:
But, what is strange, if I compile from terminal, like that, code works properly.
So, where is the error and how i can beat it?
Thank you!
All my code:
main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct vector
{
int size;
int *array;
int alreadyIn;
}vector;
vector *vectorInit(int size)
{
vector *newVec = (vector *)malloc(sizeof(vector));
if(!newVec){printf("No memory!\n"); return NULL;}
newVec->size = size;
newVec->array = (int *)malloc(size * sizeof(int));
return newVec;
}
void allocNewMemory(vector *vect, int howMuch)
{
vect->array = (int *)realloc(vect->array ,(vect->size + howMuch) * sizeof(int));
vect->size += howMuch;
}
void pushBack(vector *vect, int number)
{
int howMuch = 5;
if(vect && vect->alreadyIn < vect->size)
{
vect->array[vect->alreadyIn] = number;
vect->alreadyIn++;
}
else
{
printf("Alloc new memory for %d elements...\n", howMuch);
allocNewMemory(vect, howMuch);
pushBack(vect, number);
}
}
void printVector(vector *vect)
{
for (int i = 0; i < vect->alreadyIn; i++)
{
printf("%d ", vect->array[i]);
}
printf("\n");
}
int main()
{
int startSize = 4;
vector * vec = vectorInit(startSize);
for (int i = 0; i < 6; i++)
{
pushBack(vec, i+1);
}
printVector(vec);
return 0;
}
You never initialize the alreadyIn member in the structure. That means its value will be indeterminate (and seemingly garbage or random).
You need to explicitly initialize it to zero:
vector *vectorInit(int size)
{
vector *newVec = malloc(sizeof(vector));
if(!newVec)
{
printf("No memory!\n");
return NULL;
}
newVec->size = size;
newVec->array = malloc(size * sizeof(int));
newVec->alreadyIn = 0; // Remember to set this to zero
return newVec;
}
This problem should have been easy to detect in the debugger.
Also note that I removed the casts from malloc. One should not cast the result of malloc, or really any function returning void *.

assigned value to dynamic array created in void function doesnt return the same value in main()

I have a problem with dynamic arrays in C. My program was working perfectly, but I was asked to put the creation of dynamic array into a seperate void. I did it, and it still worked great, but then I had to assign a value to a certain point of the created array in void, and make it return the said value, however, what I get is a random value. The function works by sending a pointer and the lenght of required array into void, and then makes the pointer into a dynamic array.
#include <stdio.h>
#include <stdlib.h>
#define MAX 255
void ieskom (int skaiciai[],int n, int *de, int *me, int *n1, int *n2)
{
int i = 0;
int j = 0;
int nr1 = 0;
int nr2 = 0;
int temp = 0;
int temp1 = 0;
int eile = 0;
int eile1 = 0;
int *did;
did = (int*)calloc(n,sizeof(int));
if (did==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
int *maz;
maz = (int*)calloc(n,sizeof(int));
if (maz==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
i = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] < skaiciai[i+1])
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
}
else
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
j = j + 1;
}
}
j = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] > skaiciai[i+1])
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
}
else
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
j = j + 1;
}
}
*de = did[eile];
*me = maz[eile1];
*n1 = nr1;
*n2 = nr2;
free(did);
free(maz);
}
/*int masyvas(x)
{
int y;
y = (int*)malloc(x*sizeof(int));
return y;
}*/
void *masyvas (int *skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
skaiciai[2] = 5;
return skaiciai;
}
int main()
{
int n1 = 0;
int n2 = 0;
int de = 0;
int me = 0;
int i = 0;
int n = 0;
int *skaiciai;
scanf("%d", &n);
// skaiciai = masyvas(n); // naudojant int
masyvas(&skaiciai, n);
printf("2 = %d", skaiciai[2]);
if (skaiciai==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
for (;i < n; i++)
{
scanf("%d", &skaiciai[i]);
}
ieskom (skaiciai, n, &de, &me, &n1, &n2);
if (de > me)
{
printf("Elementu numeriai:");
printf(" %d", n1-de+1);
printf(" %d\n", n1);
printf("\nAtstumas tarp ju: %d", de-2);
}
else
{
printf("Elementu numeriai:");
printf(" %d", n2-me+1);
printf(" %d\n", n2);
printf("\nAtstumas tarp ju: %d", me-2);
}
free(skaiciai);
getchar();
getchar();
return 0;
}
The problem is in void masyvas and printf skaicia[2] - I assign a certain value to skaiciai[2], yet it prints a random one. How do I fix it?
EDIT: Thank you for your answers and explanations, it really helped me a lot! I know have solved my problem, and most importantly, I know why it was a problem in the first place.
First of all, you should translate variables and texts to english (your code lack of comments, this should apply to them too).
Next your masyvas() function returns a pointer to the allocated array (why void* ?!) but when you call it you don't get the returned value.
You have to choose: either you pass a pointer to your function (an array is a pointer, to if you want an array to be allocated from a function you have to pass a pointer to the pointer, so a int **), or you use the returned value.
Allocating with returned value:
// this function allocates a int* tab of size n and set one value
int *allocate_tab(int n) {
int *tmp;
tmp = malloc(n*sizeof(int));
if (tmp == NULL) {
return(NULL); // failed
}
tmp[2] = 5;
return(tmp);
}
// in main (or other function)
int *mytab;
mytab = alloc_tab(45);
Allocating by passing a pointer to the array:
void alloc_tab(int **tab, int n) {
*tab = malloc(n*sizeof(int));
if (*tab == NULL) {
return;
}
(*tab)[2] = 5;
}
// in main (or other)
int *mytab;
alloc_tab(&mytab, 45);
If you can't understand this stuff I guess you should read more about memory, allocation and pointers.
You need to pass a pointer-to-pointer here and do not need to return anything.
void masyvas (int **skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
(*skaiciai)[2] = 5;
}
When you declare int *skaiciai, the variable is a pointer to type int. skaiciai holds the address that points to an int. When you pass &skaiciai, you're passing the address of the address that points to an int. So because this is an address of an address, its a double pointer.

Get value of structure inside a structure array

typedef struct{
int number;
char name[100];
} Apple
typedef struct{
Apple *apple;
int bit[2];
} AppleArray;
int main(){
AppleArray *aArray;
loadApple(&aArray);
}
loadApple(AppleArray **aArray){
*aArray = NULL;
for(i=0; i<100; i++){
*aArray = realloc(*aArray, (i+1) * sizeof(AppleArray));
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
I want to have an AppleArray with specific size. Each AppleArray will have two Apple. However, I get segfault when i assign NULL to aArray[i]->apple. What is the problem there?
EDIT :
loadApple(AppleArray **aArray){
*aArray = malloc(100 * sizeof(AppleArray));
for(i=0; i<100; i++){
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
You can call realloc() only on an address that was returned to you by an prior memory allocation function like malloc()or calloc() otherwise it gives you Undefined Behavior.
C99 Standard 7.20.3.4-3: The realloc function:
void *realloc(void *ptr, size_t size);
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined.
Apart from what Als has mentioned above, you are also having an array out-of-bounds read problem as after your loop, i value will be 100 and you are trying to access aArray[100] whereas in your logic (though incorrect) your would have allocated memory only till aArray[99].
Your loadApple function can be rewritten as below:
loadApple(AppleArray **aArray)
{
*aArray = NULL;
*aArray = malloc(100 * sizeof(AppleArray));
//I have shown index as 0 here just as an example.
(*aArray)[0].apple = NULL;
(*aArray)[0].apple = malloc(2 * sizeof(Apple));
}
This code should also give the same behavior which the logic of your code is trying to achieve.
<pre>
#include "stdio.h"
#include "stdlib.h"
#define MAX_SIZE 5
#define NAME_SIZE 100
#define APPLE_NUM 2
typedef struct
{
int number;
char name[NAME_SIZE];
}Apple;
typedef struct
{
Apple* apple;
int bit[2];
}AppleArray;
void printApple(AppleArray** aArray)
{
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
fprintf(stderr, "%4d: bit[0] = %d, bit[1] = %d\n", i, (*aArray + i)->bit[0], (*aArray + i)->bit[1]);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
fprintf(stderr, "\tapple[%d]: number = %d, name = %s\n",
j,
(*aArray + i)->apple[j].number,
(*aArray + i)->apple[j].name);
}
printf("\n");
}
}
void loadApple(AppleArray **aArray)
{
*aArray = NULL;
int i;
for(i = 0; i < MAX_SIZE; i++)
{
AppleArray* tmp = (AppleArray*)realloc(*aArray, (i+1) * sizeof(AppleArray));
if (tmp != NULL)
{
*aArray = tmp;
}
else
{
//error
free(*aArray);
*aArray = NULL;
exit(0);
}
/*SEGFAULT here*/
//aArray[i]->apple = NULL;
(*aArray + i)->apple = NULL;
(*aArray + i)->bit[0] = i;
(*aArray + i)->bit[1] = i + 1;
/*
int j;
for (j = 0; j < 2; j++)
{
(*aArray + i)->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1));
}
*/
(*aArray + i)->apple = (Apple*)realloc(NULL, sizeof(Apple) * APPLE_NUM);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
(*aArray + i)->apple[j].number = j;
snprintf( (*aArray + i)->apple[j].name, NAME_SIZE, "apple_%d_%d", i, j);
}
}//for
}
void destroyApple(AppleArray* thiz)
{
if (thiz == NULL)
{
return;
}
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
free(thiz[i].apple);
thiz[i].apple = NULL;
}
free(thiz);
}
int main()
{
AppleArray *aArray;
loadApple(&aArray);
printApple(&aArray);
destroyApple(aArray);
return 0;
}

Unable to get array of structures initialized

I am passing a pointer to function and I want to initialze the array of structures in called function and want to use that array main function. But I was unable to get it in main function.
Here is my code:
typedef struct _testStruct
{
int a;
int b;
} testStruct;
void allocate(testStruct** t)
{
int nCount = 0;
int i = 0;
printf("allocate 1\n");
t = (testStruct**)malloc(10 * sizeof(testStruct));
for(i = 0; i < 10; i++)
{
t[i] = (testStruct *) malloc( 10 * sizeof(testStruct));
}
for(nCount = 0 ; nCount < 10; nCount++)
{
t[nCount]->a = nCount;
t[nCount]->b = nCount + 1;
printf( "A === %d\n", t[nCount]->a);
}
}
int main()
{
int nCount = 0;
testStruct * test = NULL;
int n = 0;
allocate(&test);
for(nCount = 0 ; nCount < 10; nCount++ )
{
if (test == NULL)
{
printf( "Not Allocated\n");
exit(0);
}
//printf("a = %d\n",test[nCount]->a);
/*printf("a = %d\n",test->a);
printf("b = %d\n",test->b); */
}
return 0;
}
Please note I have to pass double pointer to function as it is required.
Thank you for helping.
#include <stdio.h>
#include <stdlib.h>
typedef struct _testStruct
{
int a;
int b;
} testStruct;
void allocate(testStruct** t)
{
int nCount = 0;
printf("allocate 1\n");
testStruct *newT = (testStruct*)malloc(10 * sizeof(testStruct));
for(nCount = 0 ; nCount < 10; nCount++)
{
newT[nCount].a = nCount;
newT[nCount].b = nCount + 1;
printf( "A === %d\n", newT[nCount].a);
}
*t = newT;
}
int main()
{
int nCount = 0;
testStruct * test = NULL;
allocate(&test);
for(nCount = 0 ; nCount < 10; nCount++ )
{
printf("a = %d\n",test[nCount].a);
printf("a = %d\n",test[nCount].b);
}
return 0;
}
Should work.
t = (testStruct**)malloc(10 * sizeof(testStruct));
is assigning to t, not test. Perhaps you want
*t = (testStruct*)malloc(10 * sizeof(testStruct));
instead? I'm not sure, I tend to get lost when so many pointers are around. Anyway, you don't seem to be assigning anything into the pointer you pass to your function.
You say you want to create an array of structures, but your allocate function creates a data structure more like two-dimensional array. In addition, you don't return that structure back to the caller in any way that makes sense. I think you have come confusion about pointers, malloc() and all of the indirection you're doing. Check out #Ed Heal's answer for a corrected program.

Resources