I am allocating memory for my float3x3 matrix as such:
typedef float float3x3[3][3];
float3x3 *g = malloc(sizeof g);
g = &(float3x3){
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
printfloat3x3(*g);
The above compiles, however I am allocating space for *g then setting g's pointer to a static 3x3 matrix. Not exactly what I want to do if I want to free g.
How can I initialize g using a compound literal after allocation? I tried this but it wont compile:
typedef float float3x3[3][3];
float3x3 *g = malloc(sizeof g);
g = (float3x3){
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
printfloat3x3(*g);
free(g);
cc -fsanitize=address -Wall -Wextra -pedantic -O2 -o test-gmath test-gmath.c gmath.c -lm
test-gmath.c: In function ‘GMATH_Tests’:
test-gmath.c:69:11: warning: assignment to ‘float (*)[3][3]’ from incompatible pointer type ‘float (*)[3]’ [-Wincompa
tible-pointer-types]
69 | g = (float3x3){
| ^
test-gmath.c:75:9: warning: ‘free’ called on unallocated object ‘({anonymous})’ [-Wfree-nonheap-object]
75 | free(g);
| ^~~~~~~
test-gmath.c:69:23: note: declared here
69 | g = (float3x3){
| ^
(3 of 11): warning: assignment to ‘float (*)[3][3]’ from incompatible pointer type ‘float (*)[3]’ [-Wincompatible-poi
nter-types]
First, you need to allocate the size of the structure, not the pointer:
float3x3 *g = malloc(sizeof *g);
Then to initialize the contents, you can use memcpy()
memcpy(g, &(float3x3){
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
}, sizeof *g);
Your code causes a memory leak because you're reassigning the pointer to point to the memory of the compound literal. That's also why free() fails, because it no longer points to the memory returned by malloc().
Typedef arrays are confusing. It's not possible to assign an array. Yoyu can't do:
float a[3][3];
float b[3][3];
a = b;
The same way you can't:
typedef float float3x3[3][3];
float3x3 *a = ...
*a = anything
Do not use typedef arrays. Use a structure.
struct float3x3 {
float v[3][3];
};
struct float3x3 *g = malloc(sizeof(*ga));
*g = (struct float3x3){
.v = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 },
}
};
In this code snippet
typedef float float3x3[3][3];
float3x3 *g = malloc(sizeof g);
The pointer g has the type float ( * )[3][3].
And sizeof( g ) is equivalent to sizeof( float ( * )[3][3] ). So you are allocating memory for a pointer not for an array of the type float3x3.
And this statement
g = &(float3x3){
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
results in a memory leak because at first the pointer pointed to a dynamically allocated memory and then it was reassigned with the address of the compound literal. So the address of the allocated memory is lost.
Instead of using a pointer of the type float ( * )[3][3] you need to use a pointer of the type float ( * )[3].
#include <string.h>
//...
typedef float float3x3[3][3];
float ( * g )[3] = malloc( sizeof( float3x3 ) );
memcpy( g, (float3x3){ { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }, sizeof( float3c3 ) );
Related
I'm working on an exercise and I can't declare and initialize on the same line, and with these instructions I don't know how I can do, I tried multiple tips but no one works.
Can you help me please ? I want to initialize my array in the next line.
This, is working fine:
int tab[n];
tab[0] = 5;
And, this, is not working
int tab[];
tab[n] = { 0 };
Issue #1. The compiler needs a size when declaring an array.
int tab[];
Will not compile.
C does allow for variable sized arrays.
int n = 5;
int tab[n];
Issue #2. You attempt to assign to the nth element in an array with size n, which is out of bounds, and will not work.
Issue #3. You cannot assign to an array directly, so this will not work:
int n = 5;
int tab[n];
tab = { 0 };
And the initializer syntax will not work in this context. You would have to use it inline with the declaration. Although, a variable-sized array may not be initialized this way anyway.
Legal:
#define N 5
int main() {
int tab[N] = { 0 };
return 0;
}
Illegal:
int main() {
int n = 5;
int tab[n] = { 0 };
return 0;
}
To assign an all zero byte pattern to int tab[n] after definition:
memset(tab, 0, sizeof tab);
If code needs a more complex assignment, code could then use individually for each array element as needed.
tab[0] = 5;
...
C has something which is called flexible array members.
struct flex
{
size_t size;
int x[];
};
struct flex a = {5, {1,2,3,4,5}};
int main(void)
{
struct flex *z;
z = malloc(sizeof(*z) + 3 * sizeof(z -> x[0]));
z -> size = 3;
}
You cannot specify an empty pair of brackets to declare a variable.
int tab[]; /* error */
And adding the assigment you add later, just gets things worse:
tab[5] = 3;
The first thing you need to learn is that an assignment is some kind of expression that allows you to make a calculation, while a declaration is a statement (not an expression) that allows you to introduce a new object (and allows you to initialize it)
An initializer allows an incomplete declaration to become complete, so in the case you do both things at the same time (declare and initialize) the code above, written in this form:
int tab[] = { [0] = 3, [1] = 5, [2] = 8 };
makes the array declaration to be complete and will initialize the elements as shown.
You can go further, and also specify an array length, and all the unspecified elements in the initializer will be initialized to 0 (in this case the object is complete from the declaration, but what is incomplete is the initializer, which fills the holes with zeros).
int tab[20] = { [0] = 3, [1] = 5, [19] = 6 };
(if the indices will go up from 0, you can avoid the [index] = , as in
int tab[20] = { 3, 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 6 };
)
Had you written your code as one declaration:
int tab[] = { [5] = 3 };
that would have been valid.
#include <stdio.h>
#define NELEM(_arr) (sizeof (_arr) / sizeof (_arr)[0])
int tab[] = { [5] = 3 };
int main()
{
for (int i = 0; i < NELEM(tab); i++)
printf("tab[%d] = %d\n", i, tab[i]);
return 0;
} /* main */
will show:
$ a.out
tab[0] = 0
tab[1] = 0
tab[2] = 0
tab[3] = 0
tab[4] = 0
tab[5] = 3
$ _
I have a program that has to use ShowMe (int *p) and from the main function when it is called it needs to pull the values out of typedef Pyramid A.
this is the typedef struct declaration
typedef struct _Pyramid
{
double element [N][N];
} Pyramid;
I have gotten incompatible errors, I understand they're not the same type. I have tried casting and have been told I can't do that.
I have tried every-way I'm currently aware of to get this to work. So how would I call the function ShowMe (int *p) in main and pass it the values of Pyramid A?
I will post the code if asked. But I'm tired of being told what I'm doing wrong (which I mostly had already figured out from the errors) without any direction on what to do right. I will emphasize again. I'm new to C and I'm very tired and have worked on something for more than a couple of days before I post.
#include <stdio.h>
#include <stdlib.h>
#define N 8
typedef struct _Pyramid{
double stone [N][N];
} Pyramid;
int data[N*N];
Pyramid ShowMe(int *p) // pass in data and return Pyramid
{
int i;
int j;
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
printf("%g ", a.stone[i][j]);
}//Inner for
printf("\n");
}//Outer For
}//IZZ
int main(int argc, char **argv)
{
// special case that allows us to initialize this way
Pyramid A = {10, 4, 2, 5, 1, 0, 0, 0,
3, 9, 1, 2, 1, 0, 0, 0,
-7, -5, 1, -2, -1, 0, 0, 0,
-3, -5, 0, -1, 0, 0, 0, 0,
-2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
ShowMe(int *A);
}//main
Your stumbling block is more about handling the struct as a parameter. A struct is simply a data type in C. It is passed as a parameter just as any other data type (int, long, char, etc...) and follows the same rules.
The convenience of a typedef allows you to specify the parameter as Pyramid var rather than having to use the full struct Pyramid var as you would without it. In fact, you don't even need the _Pyramid name for the struct when using a typedef, e.g.
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
Above, the typedef simply aliases an unnamed struct containing an array of doubles to the pyramid_t name, which you can use in declaring instances of the struct, e.g.
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
Whether you include _Pyramid or not is up to you. (without it, you simply lose the ability to refer to struct _Pyramid as a declared type).
Your declaration of int data[N*N]; is a red-herring, a distraction of no consequence that isn't relevant to what you are attempting to do. You initialize an instance of your struct in main(). You simply need to pass the struct (or better, a pointer to your struct) to your showme[1] function in order to have the values available for printing there.
For example, including the typedef to specify you are passing the struct as a parameter (where the function receives a copy of the struct) you output the values using the dot '.' operator as you have in your function, e.g.
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
You would then call your function in main() as:
showme (a); /* passing a copy of the struct to showme() */
(note: the function receives a copy of the struct -- so try changing some of the array values and then print the contents again back in main() ... any changes made are lost)
A more efficient way of passing the struct would be to pass a pointer to the struct, so that all that is being passed is the address of where the structure is stored in memory. Not only does that avoid making a copy of the struct, but by passing the address, any changes you make to the structure values are then preserved (because you are directly changing the values of the original struct in memory -- not simply making changes to a copy). When you pass a pointer to a struct (or anytime you are accessing values of a struct through a pointer), you use the arrow operator (->) to access the struct members. For example, you could have just as easily have declared showme() to take a pointer to pyramid_t instead of a struct, e.g.
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p->stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
To pass a pointer to your struct in main(), you simply use the unary '&' operator (address of) to pass the address of a, e.g.
showme (&a); /* pass pointer to prevent duplicating struct */
Now if you made changes to the array values in the function, the changes would be visible back in main() because you changed the values where they were stored in memory rather than operating on a copy passed to the function.
Look at both examples and understand the differences both in declaring the showme() function and how it is called in main(). The first example passing a copy of the struct and using the dot-operator to access the member would be:
#include <stdio.h>
#include <stdlib.h>
#define N 8 /* good job - if you need a constant, #define one (or more) */
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
int main (void) { /* unless using argc, argv, use void */
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
showme (a); /* passing a copy of the struct to showme() */
return 0; /* main() is type 'int' and returns a value */
}
To pass a pointer containing the address of the original struct, you would simply change the declaration of showme() and the operator used to access the struct members:
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
...
printf("%3g ", p->stone[i][j]);
...
}
And, as explained above, you would simply call showme() with the address of a, e.g.
showme (&a); /* pass pointer to prevent duplicating struct */
In either case the output would be the same, e.g.
Example Use/Output
> bin\pyramid-struct.exe
10 4 2 5 1 0 0 0
3 9 1 2 1 0 0 0
-7 -5 1 -2 -1 0 0 0
-3 -5 0 -1 0 0 0 0
-2 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Look things over and understand the differences, and let me know if you have further questions.
footnotes:
[1] While not an error, C style generally avoids the use of MixedCase or camelCase variables and the use of all-uppercase names (reserving all uppercase names for constants or macros), instead using variables names of all lowercase. While this is an issue of style, and completely up to you, it can lead to the wrong first-impressions in some settings.
Casting the type Pyramid* as an int* will violate the strict aliasing rule and could cause some undefined behaviors. Passing a char* instead of an int* for ShowMe() is a possible workaround, since char pointers are an exception to the strict aliasing rule. For more information and workarounds, check this post.
I have the following code with an intention to initialize member b. This should happen for all the MAX_SIZE structs.
enum { MAX_SIZE = 10 };
struct some
{
int a, b;
}
many[MAX_SIZE] = { {.b = 5} };
int main()
{
int i;
for (i = 0; i < MAX_SIZE; i++)
{
printf("%d, %d\n", many[i].a, many[i].b);
}
}
I need the output to look like:
0, 5
0, 5
0, 5
... (10 times)
But, the actual output is:
0, 5
0, 0
0, 0
... (10 times)
How to get the required output without requiring an explicit for loop for assigning the values? I know in C++, this is accomplished by providing a constructor for the struct initializing b only.
It's not C Standard, but with this gcc extension you can do this :
struct some many[10] = { [0 ... 9].b = 5 };
It works with clang >= 5 too.
I am trying to initialize a 2d array of ints inside a struct.
In the beginning of my program (global access) I have created a struct, and an array of this struct:
struct block {
int theblock[3][3];
};
struct block blockArray[6];
Then I am trying to initialize the array of structs in a function:
void afunction() {
int block1[3][3] = {
{0, 1, 0},
{0, 1, 0},
{0, 1, 0}
};
blockArray[0].theblock = block1;
}
Compiler error:
error: incompatible types when assigning to type 'int[3][3]' from type 'int[*][3]'
Could anyone please explain what I have done wrong here, I know this is pretty basic stuff but I have really tried to read up and solve this on my own. I am coming from Java and trying to learn C.
Create a temporary struct and assign it to your element of the array of structs:
struct block temp = { { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} } } ;
blockArray[0] = temp ;
or just use your array and copy it:
int temp[3][3] = { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} } ;
assert( sizeof( temp ) == sizeof( blockArray[0].theblock ) ) ;
memcpy( blockArray[0].theblock , temp , sizeof( temp ) ) ;
You can not copy an array this way in C. For that matter, I didn't think you could do it in Java either.
You can copy the pointers around, for instance
blockArray[0].theblock = block1;
But all this will do is to have blockArray[0].theblock point at the same address as &block1[0]. It does not copy any content, it's a shallow copy.
You'll have to copy the members over with memcpy() or in loop(s):
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
blockarray[0].theblock[i][j] = block1[i][j];
I'm new to C, and I am trying to write a function which counts the number of 1's along each column in a matrix made out of 1's and 0's. Here's my code:
#include <stdio.h>
void *countCols(int *output, int rows, int cols, int **matrix[5][5])
{
/*(int *output) is the pointer which we want the output stored at.
*(int rows) is the number of rows in our matrix. This is found to be 5 at runtime
*(int cols) is the number of cols in our matrix. This is also found to be 5 at runtime.
*(int **matrix[5][5]) is a matrix containing the 1's and 0's.
*/
int colnum;
int rownum;
int counts[cols];
for (colnum = 0; colnum < cols; colnum ++)
{
for (rownum = 0; rownum < rows; rownum ++)
{
counts[colnum] += matrix[rownum][colnum];
}
}
/*
*We store the result in output.
*/
output = counts;
}
int main(int argc, char **argv)
{
/*
*First, we create our matrix.
*/
int matrix[5][5] = {{0, 1, 1, 0, 1},
{1, 0, 1, 1, 0},
{1, 0, 0, 0, 1},
{0, 0, 1, 1, 1},
{1, 0, 1, 1, 0}};
int *Cs;
countCols(Cs, 5, 5, matrix);
/*Here, we tally up our 1's column by column.*/
int i;
printf("The column counts are:\n");
for (i = 0; i < 5; i ++)
{
printf("%d\n", Cs[i]);
/*Next, we print the counts on separate lines.*/
}
/*Finally, we return 0*/
return 0;
}
So, I was expecting:
The column counts are:
3
1
4
3
3
However, to my surprise, I got:
The column counts are:
1768709983
1935631202
1953653108
1767992671
1600061550
What's going on here? It's also worth noting that, when I compiled, I got these warnings:
C.c In function 'countCols':
C.c:12.22: warning: assignment makes integer from pointer without a cast
counts[colnum] += matrix[rownum][colnum];
C.c In function 'main':
C.c:27.23: warning: passing argument 4 of 'countCols' from incompatible pointer type
countCols(Cs, 5, 5, matrix);
C.c:3:7: note: expected 'int ** (*)[5]' but argument is of type 'int (*)[5]'
void *countCols(int *output, int rows, int cols, int **matrix[5][5])
Any suggestions would be greatly appreciated.
Edit:
Just to be clear, I'm passing a pointer to the matrix, not the matrix itself, into countCols.
Your function doesn't return anything, so the return type should be void, not void*.
First of all the prototype of your function should be something like this:
void countCols(int *output, int rows, int cols, int matrix[5][5])
it could be improved though.
Then, inside the body of the function you do:
output = counts;
where you set your pointer to an array that has local scope, thus it will be de-allocate when the function terminates. However, your pointer, Cs, will not preserve changes, since it's passed by value to the function.
Use dynamic allocation instead and don't forget to free it when you are done.
With dynamic allocation your function should be like this (notice that the prototype differs from the one I suggested above):
// Pass a pointer to the integer pointer for 'output'
void countCols(int **output, int rows, int cols, int matrix[5][5])
{
int colnum;
int rownum;
// PERFORM DYNAMIC ALLOCATIONS and USE 'output', instead of 'count'
*output = malloc(sizeof(int) * cols);
for (colnum = 0; colnum < cols; colnum ++)
{
for (rownum = 0; rownum < rows; rownum ++)
{
(*output)[colnum] += matrix[rownum][colnum];
}
}
// NO NEED FOR THIS
// output = counts;
}
and the main, where the calling and the free-ing of the memory are remarkable:
int main(int argc, char **argv)
{
/*
*First, we create our matrix.
*/
int matrix[5][5] = {{0, 1, 1, 0, 1},
{1, 0, 1, 1, 0},
{1, 0, 0, 0, 1},
{0, 0, 1, 1, 1},
{1, 0, 1, 1, 0}};
int *Cs = NULL;
countCols(&Cs, 5, 5, matrix);
/*Here, we tally up our 1's column by column.*/
int i;
printf("The column counts are:\n");
for (i = 0; i < 5; i ++)
{
printf("%d\n", Cs[i]);
/*Next, we print the counts on separate lines.*/
}
free(Cs);
/*Finally, we return 0*/
return 0;
}
Appendix
As The Paramagnetic Croissant said:
"Pay attention to the warnings. An array is not a pointer, a pointer is not an array, and a multidimensional array is not a pointer-to-pointer."
Make sure you take a good look at the Arrays and Pointers section from here.
I think you mean the following function declaration:)
void countCols(int *output, int rows, int cols, int ( *matrix )[5] );
instead of
void *countCols(int *output, int rows, int cols, int **matrix[5][5]);
because you call it like
countCols(Cs, 5, 5, matrix);
Take into account that you did not allocate memory that would be pointed to by pointer Cs
int *Cs;
However inside the function you assign it the address of the first element of a local array.
So the program has undefined behaviour.
You could write simply
int Cs[5];
and inside the function use it instead of the local array.
So remove the definition of the local array
int counts[cols];
from the function and use directly parameter output