parse one struct to function from an array of structs - c

I am new to C, but not to programming. I have been roped into modifying a C program to make it gather multiple pieces of data and put them in an array. I am not allowed to post actual source code, so I have made the following example which illustrates what I am trying to do:
#include <windows.h>
typedef struct
{
int size;
long rpm;
} ENGINE;
typedef struct
{
int doors;
int wheels;
ENGINE engine;
} CAR;
int newCar(CAR *car)
{
ENGINE eng;
eng.rpm=30000;
eng.size=1600;
car->doors=4;
car->wheels=4;
car->engine=eng;
return 0;
}
int getCars(CAR *cars[], int n)
{
int i = 0;
for (i=0; i<n; i++)
{
newCar(cars[i]);
}
return 0;
}
int carCount(int *count)
{
*count = 4;
return 0;
}
int main()
{
int n = 0;
CAR *cars = (CAR*) malloc(sizeof(CAR));
carCount(&n);
cars = (CAR*)realloc(cars, n * sizeof(CAR));
cars[1].doors = 2;
getCars(&cars,n);
}
The code above compiles but fails when I try to set members of the car struct inside the newCar routine. I'm not sure whether my realloc on the cars array is doing what I want it to, I based it on some other posts on stackoverflow. Does it look ok?
How can I access the members of car from the newcar routine?
Is this a reasonable way of doing this?
Many thanks :)

You don't need double indirections!
A simple pointer to CAR can point to different CARs.
Create space for the number of CARs you need: ok
A pointer to the first CAR in that space can easily be made to point to the other CARs.
CAR *cars = malloc(sizeof(CAR));
if malloc didn't fail cars points to a space large enough to hold 1 CAR
cars = realloc(cars, n * sizeof(CAR));
if realloc didn't fail cars now points to a space large enough to hold n cars
pass that pointer to your functions, along with how many cars it points to
getCars(cars, n);
and use the pointer in the functions
int getCars(CAR *cars, int n)
{
int i = 0;
for (i=0; i<n; i++)
{
/* here, cars[0] is the first car; cars[1] is the second ... */
/* we can pass the address with &cars[i] */
/* or make arithmetic with the pointer itself: */
newCar(cars+i);
}
return 0;
}

In order to use malloc for example you need the stdlib.h header. Since you are casting the pointer from malloc to (CAR*) the compiler assumes that malloc is returning an int and no warning is generated.

In getCars, you define cars as CAR *cars[], that is, array of pointers to CAR.
In main, &cars is a pointer to array of CARs.
The code happens to compile perhaps because both resolve to CAR**.
I would rewrite the code in the following way:
int newCar(CAR** car)
{
*car = (CAR*)malloc(sizeof(CAR));
ENGINE eng;
eng.rpm=30000;
eng.size=1600;
(*car)->doors=4;
(*car)->wheels=4;
(*car)->engine=eng;
return 0;
}
int getCars(CAR *cars[], int n)
{
int i = 0;
for (i=0; i<n; i++)
{
newCar(&cars[i]);
}
return 0;
}
int main()
{
int n = 0;
CAR** cars = (CAR**) malloc(sizeof(CAR*));
carCount(&n);
cars = (CAR**)realloc(cars, n * sizeof(CAR*));
getCars(cars,n);
cars[1]->doors = 2;
}
etc.

The reason why your code fails, is that in main, cars is a simple scalar variable, and you call a subroutine with its address as argument. In getCars, cars is an array of pointer, so cars[i], read ahead of the address you passed as argument. And this is where its wrong, because the address is an address of a single scalar variable, not the address of a table.
To get right, you should call the subroutine with the value of main's cars, which is exactly the address of the table your created with malloc/realloc. Note that in that case, the subroutine prototype will simply be
int getCars(CAR *cars, int n)

You would typically use malloc(n * sizeof(CAR)). The realloc function is only useful for over-the-moon-kind of programming.

Related

how can i solve this when i try to return a 2d struct from a function

this is how i declare this struct
typedef struct cache{
int vaild;
char* tag;
char* data;
}cache;
this is part of my main which called this function
struct cache **cacheA = createCache(Setnum,(int)pow(2,blocksize),cachesize);
struct cache **cacheB = createCache(Setnum,(int)pow(2,blocksize),cachesize);
and now this is my called function
struct cache ** createCache(int numset, int blocksize, int cachesize){
int numcache = (int)((cachesize/blocksize)*numset);
struct cache out[numset][numcache];
int i,j;
for (i=0; i < numset; i++){
for (j=0; j < numcache; j++){
out[i][j].tag = "0";
out[i][j].vaild = 0;
out[i][j].data ="0";
}
}
return out;
}
and when i try to compile this, it tells me that
return from incompatible pointer type
function returns address of local variable
(which points to the line "return out;")
I have no idea whats wrong with my code, i mean the type of the function return is the same as how i declear "out", so what causes this problem?
You create struct cache out[numset][numcache];
within the function prototyped as: struct cache ** createCache(...).
Then attempt to return out.
It is because struct cache [][] is typed differently than struct cache ** that you are getting the return errors.
Other comments:
1) If you truly do want a pointer to pointer to struct, then malloc or calloc will need to be used at some point to allocate memory.
2) the char * members of the struct also need to be assigned memory before assigning values. For illustration below, they are changed to char []
3) assigning values to strings does not work by using = assignment operator. Use a string function such as strcpy, sprintf, etc.
4) you've named the struct with the same symbol as that of the new type you have created, i.e. cache. In this application, the name cache is not necessary. Also, purely for style, I show the new type in CAPS. This is not necessary, but just a style I use to make the new type more recognizable in code.
In consideration of the comments above, the struct could be changed to the following:
typedef struct { /// don't need name here when it in this application
int vaild;
//char *tag;
char tag[20];//for illustration, to avoid additional dynamic allocation of memory
//char* data;
char data[80];
}CACHE;//capitalization is style only, not a necessity here.
Note, there is no name, but the new type CACHE was created. Now, you can create the function createCache:
CACHE ** createCache(int ncache, int nset)//note for simplicity of freeing this
//object later, simplify number of arguments
{
CACHE **out;
out = calloc(ncache, sizeof(CACHE *));//create array of pointers to CACHE
if(!out) return NULL;
int i;
for (i=0; i < nset; i++)
{
out[i] = calloc(nset, sizeof(CACHE));//create space for each instance
//of CACHE pointed to by array pointers
}
return out;
}
Anytime memory is created on the heap, it needs to be freed. This method will free the CACHE object memory:
void freeCashe(CACHE **a, int nset)
{
int i;
for(i=0; i<nset; i++)
{
if(a[i])free(a[i]);
}
if(a)free(a);
}
Calling these functions as shown below, will create an array of pointers, each pointing to an instance of CACHE where you can use them as intended, then free all of the memory when finished:
int main(void)
{
int cachesize = 20;
int blocksize = 20;
int numset = 10;
//move the calculation out of creation function
//to simplify freeing object later.
int numcache = (int)((cachesize/blocksize)*numset);
CACHE **a = createCache(numcache, numset);
/// use a, then free a
freeCashe(a, numset);
return 0;
}
Your function needs to allocate the memory on the heap rather than the stack. You will need to allocate space on the heap for your array of pointers, and for what they point too.
struct cache ** createCache(int numset, int blocksize, int cachesize){
cache ** out;
int numcache = (int)((cachesize/blocksize)*numset);
size_t headerSize = sizeof(*out)*numset;
size_t bodySize = sizeof(**out)*numcache;
out = malloc(headerSize + (bodySize*numset));
if (out == NULL) {
/* Should probably output some message about being
* insufficient memory here. */
return NULL;
}
int i,j;
for (i=0; i < numset; i++){
/* need to assign our point */
out[i] = (cache*)(((char*)out)+(headerSize+bodySize*i));
for (j=0; j < numcache; j++){
out[i][j].tag = "0";
out[i][j].vaild = 0;
out[i][j].data ="0";
}
}
return out;
}
/* importantly, you want a way to free your allocated memory */
void destroyCache(cache ** ptr) {
free(ptr);
}
PS: You don't have to typedef your struct if you reference it with the struct keyword.
You are wanting a pointer pointer type to be returned, but in order to do that you need to dynamically allocate it. Local stack allocations (i.e. struct cache[x][y]) won't work. You will either get an error or your program will crash when attempting to use the 2D array.
The solution is to either pre-allocate space and pass it in to the function or allocate in the function itself.
Allocation In Function Example:
struct cache ** createCache(int numset, int blocksize, int cachesize){
int numcache = (int)((cachesize/blocksize)*numset);
struct cache **out = malloc(sizeof(struct cache *) * numset); // This line changed.
int i,j;
for (i=0; i < numset; i++){
out[i] = malloc(sizeof(struct cache) * numcache); // This line added.
for (j=0; j < numcache; j++){
out[i][j].tag = malloc(sizeof(char)); // This line added.
out[i][j].data = malloc(sizeof(char)); // This line added.
strcpy(out[i][j].tag, "0");
out[i][j].vaild = 0;
strcpy(out[i][j].data, "0");
}
}
return out;
}

How to walk through array of Struct in c

I have a program which creates an array or struct and go through it for processing. Initially it initialize the array with the defined nyumber of elements. Then for some number of element in array, the name is assigned.
I pretend the code that is equal to my scenario which is tested in codebloc and get the similar error. The problem is described in comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _car {
char *name;
int year;
} Car;
char *getCarName(char *name, int var);
void processCar();
void printCars(Car car[]);
int INCREMENT = 10;
int main(void)
{
processCar();
return 0;
}
void processCar()
{
// create car array with amount of INCREMENT
Car CAR_ARRAY[INCREMENT];
int a=0;
// This function assign name for Car amount 10 less than INCREMENT
while (a<INCREMENT - 2) {
char *carName;
carName = getCarName(&carName, a);
CAR_ARRAY[a].name = malloc(strlen(carName) + 1);
strcpy(CAR_ARRAY[a].name, carName);
a++;
}
printCars(CAR_ARRAY);
}
void printCars(Car car[])
{
printf("IN Car \n");
int a = 0;
// when try to call name for car amount equals to INCREMENT program terminates.
while(a<INCREMENT) {
if (car[a].name != NULL) // checking if NULL
printf("Car Name : %d -> %s\n", a, car[a].name);
a++;
}
}
char *getCarName(char *name, int var)
{
name = "Toyota";
return name;
}
What is the right way to check the struct value on struct array whether it can be called?
EDIT
I created a hack to do this as follows.
// added these right after creating array
for (a = 0; a < INCREMENT; a++)
CAR_ARRAY[a].name = NULL;
I dont know if it is a standard way or not. pls advice.
You are checking for NULL before printing, which is a good idea, but it doesn't help you here, because your last two cars are uninitialised and likely contain garbage: The name pointer is not NULL, but doesn't point to a valid address either. Segmentation violation ensues.
You should initialise all cars, not only INCREMENT - 2. Alternatively, you could initialise your cars to zero by calling memset before your initialisation:
memset(CAR_ARRAY, 0, sizeof(Car) * INCREMENT);
As an aside, the way you deal with getCarName is rather shaky as well. At the moment, your name is a pointer to a string literal. Your local variable carName does a half-hearted double duty: You try to pass it by reference (but essentially you don't) and you also return it.
Basically, you could do this in one of two ways. The easier one here is to return a pointer. in that case, you don't have to pass any string:
char *getCarName(int var)
{
static char *names[3] = {"Toyota", "Dodge", "Peugeot"};
return names[var % 3];
}
and call it like so:
char *carName = getCarName(&carName, a);
Alternatively, you could pass a char pointer by reference, i.e. as pointer to pointer to char. In that case, you don't have to return anything:
void getCarName(char **name, int var)
{
static char* names[3] = {"Toyota", "Dodge", "Peugeot"};
*name = names[var % 3];
}
Call it like so:
char *carName;
getCarName(&carName, a);
There are other scenarios here, for example if you just pass a char pointer and have getCarName fill it, but I'll leave that for now - it would make everything even more complicated.

C puzzle — pointers

Basically what I'm trying to achieve here is having global variable with array of pointers to struct which size isn't known at compile time — in my example below it's my_struct **tab. In the final version I want to call a JNI method which will initialize my array of pointers and I want to keep them for some other methods usage.
Unfortunately I'm not a C programmer and I really struggle with this problem. Below I show what I tried to do; obviously, it's not working. Any constructive feedback would be really helpful.
(Sorry for missunderstanding with includes it's supposed to be a C code )
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int tag;
} my_struct;
my_struct **tab;
void * get_pointer_to_struct() {
my_struct * s;
/* allocate memory */
if ((s = (my_struct *) malloc(sizeof (my_struct))) == NULL) {
return NULL;
}
return s;
}
void free_structures(int j) {
for (int a; a < j; a++) {
my_struct *s;
s = (my_struct *) tab[a];
/* free memory */
free(s);
tab[a] = NULL;
}
}
void init_pointers_array(int j) {
my_struct * temp_arr[j];
for (int i = 0; i < j; i++) {
temp_arr[i] = (my_struct *) get_pointer_to_struct();
temp_arr[i]->tag = i;
}
tab = temp_arr;
}
int main() {
//initialization
init_pointers_array(10);
//usage
for (int a = 0; a < 10; a++) {
if (tab[a]) {
my_struct * str_tmp = tab[a];
printf("Integer that you have entered is %d\n", str_tmp->tag);
}
}
//free mem
free_structures(10);
return 0;
}
This code is so unreadable I'm surprised anyone bothered to read it. Follow these guidelines and all your problems will be solved:
Use std::vector (or similar array class) instead of raw arrays
Don't use dynamic allocation if you don't need it, but if you do use new instead of malloc
Whenever you use dynamic allocation, do so within a class that owns the object and follows the RAII principle
Don't use global variables
my_struct * temp_arr[j];
then
tab = temp_arr;
is wrong. (Not only the placement of the * qualifier is horrible and there are superfluous casts that severely decrease code readibility, but) temp_array is a local auto array, so it will be deallocated when the function returns. Doing anything with its address afterwards results in undefined behavior. You may want to malloc()ate some memory for the struct instead (the casts are only there in order the code to be usable in C++. In C, it's strongly discouraged to make redundant typecasts):
my_struct **tab;
tab = (my_struct **)malloc(sizeof(tab[0]) * number_of_structs);
int i;
for (i = 0; i < number_of_structs; i++) {
tab[i] = (my_struct *)malloc(sizeof(tab[0][0]));
}
And for freeing it:
int i;
for (i = 0; i < number_of_structs; i++) {
free(tab[i]);
}
free(tab);
Several points:
get_pointer_to_struct can simply return the result of malloc. And change it's signature to avoid the extra casts to my_struct*.
temp_array is created on the stack, so it no longer exists when init_pointers_array exits. malloc it as well. This is your BIGGEST problem.
This is in general. You do alot of superfluous work, which bloats your code something terrible. Try to avoid redundant casts and unneeded variables.

what is causing segmentation fault in c code, dynamic allocation accross functions

I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);

how to return 1000 variables from a function in C?

How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.

Resources