I'm learning for school and I found exam task:
"Create struct with fields:
2 integers,
two-dimensional flexible array (double or float) "
I did something like that:
struct my_struct{
int firstField;
int secondField;
int columns;
int rows;
double tab[columns][rows];
}
struct my_struct sample = {2, 2, 5, 4, {0.0}}
But it does not work.How should I create struct like that?
A struct cannot have a 2D VLA variable logic array nor a 2D FAM, flexible array member like with member double tab[columns][rows];. A struct can have a final of 1 dimensional FAM.
Code can get close to OP's goal of "Create struct with fields: 2 integers, two-dimensional flexible array (double or float) " by using a flexible array member that is an array of double *.
struct my_struct {
int columns;
int rows;
double *tab[/* row */];
};
This makes tab, not a 2D array but a 1D array of double *. This is usable like a 2D array with the [][] syntax.
First allocate not only memory for my_struct, but also for the appended array of double * pointers. Then allocate memory for the double array for each pointer.
As with all allocations, good to test if the allocation succeeded. Following simple uses assert(p);
I replaced working code with some TBD to allow for OP's learning experience.
struct my_struct *my_struct_alloc(int columns, int rows) {
struct my_struct *p = malloc(sizeof *p + sizeof *(p->tab) * TBD);
assert(p);
p->columns = TBD;
p->rows = TBD;
for (int r = 0; r < p->rows; r++) {
p->tab[r] = malloc(sizeof *(p->tab[r]) * TBD);
assert(p->tab[r]);
for (int c = 0; c < p->columns; c++) { // sample, fill array w/illustrative data
static int count = 0;
p->tab[r][c] = count++; // Access like a 2D array
}
}
return p;
}
void my_struct_print(struct my_struct *p) {
for (int r = 0; r < p->rows; r++) {
for (int c = 0; c < p->columns; c++) {
printf("%.0f ", p->tab[r][c]); // Access like a 2D array
}
puts("");
}
}
void my_struct_free(struct my_struct *p) {
if (p) {
for (int r = 0; r < p->rows; r++) {
free(p->tab[r]);
}
}
free(p);
}
int main() {
struct my_struct *p = my_struct_alloc(2, 3);
my_struct_print(p);
my_struct_free(p);
}
Output
0 1
2 3
4 5
Related
How can I return an array from a function, I am trying to perform (3*3)*(3*1) matrix multiplication using this translation function and how can i get an array out of it.
#include <stdio.h>
#include <math.h>
int* translation(int x, int y, int tx, int ty) {
static int res[3][1] = {0}, xy[3][1] = {{x},{y},{1}};
int tm[3][3] = {{1,0, tx}, {0,1,ty}, {0,0,1}};
for (int i = 0; i<3; i++) {
for (int j = 0; j<3; j++) {
res[i][0] += tm[i][j]*xy[j][0];
}
}
return res;
}
int main()
{
int *arr[3][1];
arr = translation(5, 5);
printf("%d %d %d", arr[0][0], arr[0][1], arr[0][2]);
return 0;
}
"How can I return an array from a function"
You can't.
The language has no such concept.
You'll have to return something including the length to give the user of the function the information. In C the idiomatic approach is to supply a pointer to the function and to get a value (via that pointer) in return:
size_t no_idea;
void function(void *data, &no_idea);
As a user of this function you'd have to read no_idea before judging.
you question is missing a lot of information like what you want to do with your code, the variable named xy isn't defined anywhere in your code, and so on...
but for clarification, if your result matrix is of unknown size, you can wrap your array into a struct, if you don't know what is the struct, you can refer to this small tutorial about struct in c, so your struct maybe look like something like this:
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int **arr;
}Array_t;
where arr is your matrix of unknown size which will be created dynamically and arrSize_x, arrSize_y are your matrix dimensions.
so in order to create a matrix of unknow size at compile time , you should create it dynamically in the heap memory using functions like calloc or malloc, although in C99, it allowed created arrays statically of unknown size during compile time but it's not the case with struct as the struct once defined, your array is created and you cannot do something like this:
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int arr[arrSize_x][arrSize_y];
}Array_t;
but if the size of the array is known you can do something like this:
typedef struct Array_t{
int arr[3][1];
}Array_t;
to create a dynamic array, you will find in the next example code something like this:
// rows are stored in heap memory and initiated with zeros
res.arr = (int**) calloc(res.arrSize_x, sizeof(int));
// columns are also stored in heap memory and initiated with zeros
for (int i = 0; i < res.arrSize_x; ++i) {
res.arr[i] = (int *) calloc(res.arrSize_y, sizeof(int));
}
where res.arr is a pointer pointing to an array of pointers and the next diagram may simplify my explanation where the next graph expresses the created matrix in heap memory for arr of size 3 x 1:
while if the size is known, so the explanation diagram may look like this:
and when you return, you can either return by value or by reference, but if you are going to return a struct by reference then you should declare it as static.
so you can do something like this (for clarification purposes, size of matrix is unknown):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Array_t{
size_t arrSize_x;
size_t arrSize_y;
int **arr;
}Array_t;
Array_t translation(int x, int y, int tx, int ty) {
// create a struct holding the array
Array_t res;
res.arrSize_x = 3;
res.arrSize_y = 1;
// rows are stored in heap memory and initiated with zeros
res.arr = (int**) calloc(res.arrSize_x, sizeof(int));
// columns are also stored in heap memory and initiated with zeros
for (int i = 0; i < res.arrSize_x; ++i) {
res.arr[i] = (int *) calloc(res.arrSize_y, sizeof(int));
}
res.arr[0][0] = 1;
res.arr[1][0] = 2;
res.arr[2][0] = 3;
return res;
}
int main()
{
Array_t array;
// 1, 2, 3, 4 are dummy parameters
array = translation(1, 2, 3, 4);
printf("elements are :\n");
for (int i = 0; i < array.arrSize_x; ++i) {
for (int j = 0; j < array.arrSize_y; ++j) {
printf("%d\t", array.arr[i][j]);
}
printf("\n");
}
return 0;
}
and this is the output:
elements are :
1
2
3
but if size of matrix is known then you can do something like this (for clarification purposes, size of matrix is known):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Array_t{
int arr[3][1];
}Array_t;
Array_t translation(int x, int y, int tx, int ty) {
// create a struct holding the array
Array_t res;
res.arr[0][0] = 1;
res.arr[1][0] = 2;
res.arr[2][0] = 3;
return res;
}
int main()
{
Array_t array;
// 1, 2, 3, 4 are dummy parameters
array = translation(1, 2, 3, 4);
printf("elements are :\n");
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 1; ++j) {
printf("%d\t", array.arr[i][j]);
}
printf("\n");
}
return 0;
}
and this is the ouput:
elements are :
1
2
3
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
struct Array {
uint32_t* row;
};
int main()
{
struct Array* a = malloc(sizeof(struct Array) * 2);
a[0].row = malloc(sizeof(uint32_t) * 3);
a[1].row = malloc(sizeof(uint32_t) * 2);
uint32_t temp1[] = {2,3,4};
uint32_t temp2[] = {5,8};
for(int i=0;i<3;i++)
a[0].row[i] = temp1[i];
for(int i=0;i<2;i++)
a[1].row[i]= temp2[i];
for(int i=0;i<2;i++)
{
int len = sizeof(a[i].row)/sizeof(a[i].row[0]);
for(int j=0;j<len;j++)
{
printf("%d\t",a[i].row[j]);
}
printf("\n");
}
}
I have a multidimensional array. rows in the array can be of different size so i used a structure.
Now I want to print the elements in the array. But its not printing in the right way.
2 3
5 8
This is showing as my output.
int len = sizeof(a[i].row)/sizeof(a[i].row[0]);
I think there is something wrong in the above line.
please help me to print the elements of array correctly
It will not work this way as it will give you the size of the pointer in uint32_t units.
If you want to dynamically allocate the 2D array you need to keep the sizes somewhere in your data. Here is an example (access using array pointer):
typedef struct
{
size_t cols, rows;
uint32_t data[];
}Array2D;
Array2D *alloc2DArray(const size_t rows, const size_t cols)
{
return malloc(rows * cols * sizeof(uint32_t) + sizeof(Array2D));
}
void printArray(const Array2D *arr)
{
uint32_t (*array)[arr -> cols] = (uint32_t (*)[])arr -> data;
for(size_t row = 0; row < arr -> rows; row++)
{
for(size_t col = 0; col < arr -> cols; col++)
printf("%"PRIu32" ", array[row][col]);
printf("\n");
}
}
Sizes are kept in the struct and the actual data in the flexible struct member.
Remember to use the correct type to store the sizes (size_t)
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 6 years ago.
I'm trying to create a function that concatenates 2 arrays and then returns the sum array back.
I've been using the following code:
#include "stdio.h";
struct array {
int length;
int *array;
};
struct array add(struct array a, struct array b) {
int length = a.length + b.length;
int sum[length];
for (int i = 0; i < length; ++i) {
if (i < a.length) {
sum[i] = a.array[i];
} else {
sum[i] = b.array[i - a.length];
}
}
struct array c;
c.length = length;
c.array = sum;
return c;
}
int main() {
int a[] = {1, 2, 3};
struct array s1;
s1.array = a;
s1.length = sizeof(a) / sizeof(a[0]);
int b[] = {4, 5, 6};
struct array s2;
s2.array = b;
s2.length = sizeof(b) / sizeof(b[0]);
struct array sum = add(s1, s2);
for (int i = 0; i < sum.length; ++i) {
printf("%d\n", sum.array[i]);
}
return 0;
}
The output is:
1,
17,
6356568,
1959414740,
1,
1959661600
What am I doing wrong?
These three lines are very problematic:
int sum[length];
...
c.array = sum;
return c;
In the first you declare the local variable sum. In the second you make c.array point to the local variable. And in the third line you return the pointer while the local variable goes out of scope.
Since the local variable goes out of scope it no longer exists, and the pointer to it is no longer valid. Using the pointer will lead to undefined behavior.
To solve this you need to allocate memory dynamically with e.g. malloc.
sum is a local variable to the add function. When you set c.array = sum;, then the pointer c.array points to this local variable.
After the function returns, local variables are destroyed. So this pointer is now a dangling pointer. But in main you then read through this pointer.
To fix this you'll need to make a fundamental change to the design of your program. For example, use dynamic allocation in all cases for a struct array.
Arrays in C simply are a contiguous area of memory, with a pointer to their start*. So merging them involves:
Find the length of the arrays A and B, (you will probably need to know the number of elements and the sizeof each element)
Allocating (malloc) a new array C that is the size of A + B.
Copy (memcpy) the memory from A to C,
Copy the memory from B to C + the length of A (see 1).
You might want also to de-allocate (free) the memory of A and B.
Example code snippet:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define ARRAY_CONCAT(TYPE, A, An, B, Bn) \
(TYPE *)array_concat((const void *)(A), (An), (const void *)(B), (Bn), sizeof(TYPE));
void *array_concat(const void *a, size_t an,const void *b, size_t bn, size_t s)
{
char *p = malloc(s * (an + bn));
memcpy(p, a, an*s);
memcpy(p + an*s, b, bn*s);
return p;
}
// testing
const int a[] = { 1, 1, 1, 1 };
const int b[] = { 2, 2, 2, 2 };
int main(void)
{
unsigned int i;
int *total = ARRAY_CONCAT(int, a, 4, b, 4);
for(i = 0; i < 8; i++)
printf("%d\n", total[i]);
free(total);
return EXIT_SUCCCESS;
}
Try this - corrected add function:
#include <stdlib.h>
struct array add(struct array a, struct array b) {
int length = a.length + b.length;
int * sum = (int*)calloc(length, sizeof(int));
for (int i = 0; i < length; ++i) {
if (i < a.length) {
sum[i] = a.array[i];
}
else {
sum[i] = b.array[i - a.length];
}
}
struct array c;
c.length = length;
c.array = sum;
return c;
}
stdlib is required to use calloc function.
That function allocate memory for length values of int type. To be sure that memory is allocated successfully, it is recommended to check value of pointer sum after allocation, e.g.:
int * sum = (int*)calloc(length, sizeof(int));
if( sum != NULL )
{
// use memory and return result
}
else
{
// do not use pointer (report about error and stop operation)
}
As Joachim mentioned, you are returning a local variable int sum[length]; This is a bad idea. The variable sum is returned to the stack after the function exits and can be overwritten by other stack variables.
One of the ways around that is to not declare an array inside the sum function in the first place. The sum_str is declared in main. You can pass the pointer to this structure to the sum function.
The updated code is below.
#include <stdio.h>
struct array {
int length;
int *array;
};
void add(struct array a, struct array b, struct array *sum_str) {
sum_str->length = a.length + b.length;
for (int i = 0; i < sum_str->length; ++i) {
if (i < a.length) {
sum_str->array[i] = a.array[i];
} else {
sum_str->array[i] = b.array[i - a.length];
}
}
}
int main() {
int a[] = {1, 2, 3};
struct array s1;
s1.array = a;
s1.length = sizeof(a) / sizeof(a[0]);
int b[] = {4, 5, 6};
struct array s2;
s2.array = b;
s2.length = sizeof(b) / sizeof(b[0]);
struct array sum_str;
int sum_a[6];
sum_str.array = sum_a;
add(s1, s2, &sum_str);
for (int i = 0; i < sum_str.length; ++i) {
printf("%d\n", sum_str.array[i]);
}
return 0;
}
Another way is to use dynamic memory allocation as described by other answers.
How can I allocate with malloc and array of structures within and array of structures?
for expample:
struct car_t{
int price;
float kmsDriven;
};
struct garage_t{
int locationX;
int locationY;
struct car_t * car;
}
There's an array of garages, which every one of them has an array of cars.
You will have to use a loop:
#define N 42
#define M 17
struct garage_t *a = malloc(sizeof *a * N);
for (int i = 0; i < N; i++) {
a[i].car = malloc(sizeof (*a[i].car) * M);
}
Just allocate as usual, one by one.
int garage_num = 3, car_num = 5;
int i;
struct garage_t *garage;
garage = malloc(sizeof(struct garage_t) * garage_num);
for (i = 0; i < garage_num; i++) {
garage[i].car = malloc(sizeof(struct car_t) * car_num);
}
You should check if malloc()s are successful for actual use.
I have a struct like this:
typedef struct {
int sizes[3];
float **vals[3]; // an array of size 3 of float ** pointers
} mystruct;
What I'm trying to do is set these array values in a function that takes a pointer to a mystruct.
void populateStruct(mystruct *s) {
int i, j, n;
for (n = 0; n < 3; n++) {
scanf("%d", &s->sizes[n]);
// Malloc the float pointers (**vals) based on the scanned sizes
s->vals[n] = (float **)malloc(s->sizes[n] * sizeof(float *));
for (i = 0; i < s->sizes[n]; i++)
s->vals[n][i] = (float *)malloc(s->sizes[n] * sizeof(float));
// Populate the float "arrays"
for (i = 0; i < s->sizes[n]; i++) {
for (j = 0; j < s->sizes[n]; j++) {
scanf("%f", &s->vals[n][i][j]);
}
}
}
}
Here is how I'm using the function in main:
int main() {
mystruct *s1;
populateStructure(s1);
return 0;
}
This code compiles fine, but I get a seg fault when I run it. C is not a strong point of mine, so I'm not too sure what I'm doing wrong.
How are you declaring your s structure and how are you passing it?
In your function where you call populateStruct you should probably declare s:
as mystruct s and call populateStruct(&s)
or
mystruct *s;
s = malloc(sizeof(mystruct));
populateStruct(s);
mystruct *s1;
s1 is only a pointer with unpredictable value. You didn't allocate memory for the struct you need.
Dereferencing a wild (uninitialized) pointer would cause segv.
You can modify your code to either:
mystruct s1;
populateStructure(&s1);
or
mystruct *s1 = (mystruct *)malloc(sizeof(mystruct));
populateStructure(s1);
( don't forget to free s1 in the second one)