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
$ _
Related
I'm trying to assign an array to one of the fields of a typedef struct and I can't find a way to do it practically.
I've searched for this problem but all I seem to find is answers for char * arrays which is not what I'm looking for, I'm just trying to assign an array to an int array, and looking for a practical way for the code below to work without having to initialize all the variables in the struct (they will be initialized later, but I just want to set the array variable):
typedef struct {
int array[5];
int number;
} Rot;
Rot RA;
void config()
{
RA.array = {1, 2, 3, 4, 5}; //This returns an "expected expression before "{"" error
int arr[5];
int i;
for (i = 0; i < 5; i++)
{
arr[i] = i + 1;
}
RA.array = arr; //I understand why this fails, but I need to do this in a practical way
}
Please assume that config is called later and the struct and RA are all accessible to it.
RA.array = {1, 2, 3, 4, 5};
memcpy(RA.array, (int[]){1, 2, 3, 4, 5}, sizeof RA.array);
RA.array = arr;
memcpy(RA.array, arr, sizeof arr); // better: sizeof RA.array
You can use memcpy as shown in another answer. Or alternatively, copy the whole struct and not just the array, using a temporary variable in the form of a compound literal:
RA = (Rot) { {1, 2, 3, 4, 5}, 0 };
This is possible because while C doesn't allow run-time assignment of arrays, it does allow it of structs.
You can use memcpy as shown in another answer, or copy the whole struct as shown in another answer (although your question states that you just want to set the array, not the remainder of the struct).
Another option is to embed just the array into another struct:
typedef struct {
int elem[5];
} RotArr;
typedef struct {
RotArr arr;
int number;
} Rot;
Then you can access element i of the array in Rot RA as RA.arr.elem[i]. Also, you can assign values to a whole RotArr object. The remainder of your code could look something like this:
Rot RA;
void config(void)
{
RA.arr = (RotArr){{1, 2, 3, 4, 5}};
RotArr arr;
int i;
for (i = 0; i < 5; i++)
{
arr.elem[i] = i + 1;
}
RA.arr = arr;
}
Note that (RotArr){{1, 2, 3, 4, 5}} is a compound literal value of RotArr type. It could also be written as (RotArr){ .elem = {1, 2, 3, 4, 5} } or (RotArr){ .elem = { [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5 } } to be absolutely clear which parts of the compound literal are being set explicitly (any remaining parts will be set to 0), but since it only has a single member, these forms of the compound literal value are a bit over-the-top.
The following works according to C syntax. Not sure this is what you wanted.
#include <string.h>
#include <stdio.h>
typedef struct {
int array[5];
int number;
} Rot;
Rot RA = {{1,2,3,4,5}};
void main()
{
RA = (Rot) {{5, 6, 7, 8, 9}};
int arr[5];
int i;
for (i = 0; i < 5; i++)
{
arr[i] = i + 1;
}
memmove(RA.array, arr, sizeof(RA.array));
// OR
int l = sizeof(arr)/sizeof(arr[0]);
for(int i =0 ; i < l ; ++i) {
*(RA.array + i) = *(arr + i);
printf("%d\n",RA.array[i]);
}
}
Moreover, use memmove since that allows memory overlap.
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'm a novice in C and I need a structure to pass constant two-dimensional arrays to function as one parameter. I want to make this
const int a_size_x = 20;
const int a_size_y = 30;
const int a_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};
const int b_size_x = 20;
const int b_size_y = 30;
const int b_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};
void function(const int array[], int arr_size_x, int arr_size_y){
for (int i = 0; i < arr_size_x; i++)
{
for (int j = 0; j < arr_size_y; j++)
{
printf("%i ", array[i][j];
}
printf("\n");
}
function(a_output_array, a_size_x, a_size_y);
function(b_output_array, b_size_x, b_size_y);
easier to be able to call function(a) like this:
const struct OUTPUT
{
const int size_x;
const int size_y;
const int array[size_x][size_y];
};
struct OUTPUT a = {.size_x = 20, .size_y = 30, .array = {{...}, ..., {...}};
....
struct OUTPUT z = {.size_x = 30, .size_y = 20, .array = {{...}, ..., {...}};
function(const struct OUTPUT out){
for (int i = 0; i < out.size_x; i++)
{
for (int j = 0; j < out.size_y; j++)
{
printf("%i ", out.array[i][j];
}
printf("\n");
}
function(a);
function(b);
but of course compiler says that size_x and size_y is undeclared in struct declaration.
I've read about flexible array members, but there's dynamic memory allocation needed, and in AVR Harvard architecture malloc can't work in program memory, where i put all this data.
Is there some way to do it in C? May be, in C++?
UPDATE Answer that worked for me - create a one-dimensional array of lenght 2 + width*height where first two members are true width and height and use a pointer to work with this. Here's an example function to print out this array:
char arr [11] =
{
3 // width
3 // height
1, 2, 3,
4, 5, 6,
7, 8, 9
}
void print_array(char *ptr)
{
char width = *ptr++;
char height= *ptr++;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
print("%c\t", *ptr++);
}
print("\n");
}
}
print_array(arr);
For most compilers, 2D arrays can be refered to as 1D as such:
matrix[3][3]=[1,2,3
4,5,6
7,8,9]
Index in 1D is calculated by row size*row number. For example: matrix[5]=6.
This means you can pass only 1 parameter, the row length, and by calculating the length of the whole vector you can deduce the 2nd parameter (number of rows).
You can add the row length parameter to the end of your array, and by so passing the array only, if that helps.
When declaring an array with an initializer, the bounds of the array must be constants. A variable with a const qualifier does not qualify as a constant. You can however use a macro which does a text substitution:
#define A_SIZE_X 2
#define A_SIZE_Y 3
const int a_output_array[A_SIZE_X][A_SIZE_Y] = {{3,4,5},{6,7,8}};
#define B_SIZE_X 2
#define B_SIZE_Y 3
const int b_output_array[B_SIZE_X][B_SIZE_Y] = {{1,2,3},{4,5,6}};
When passing a 2D array to a function, the definition must say that it expects a 2D array. Your is expecting const int array[] which is a 1D array.
You can have a function accept arrays with different bounds if the bounds are specified first in the definition:
void function(int arr_size_x, int arr_size_y, const int array[arr_size_x][arr_size_y]) {
You can then call it like this:
function(A_SIZE_X, A_SIZE_Y, a_output_array);
function(B_SIZE_X, B_SIZE_Y, b_output_array);
Side note first, the first snippet has a wrong signature and your compiler should warn you:
void function(const int array[], int arr_size_x, int arr_size_y){
here, array is a pointer to int (in a function signature, an array automatically gets adjusted to a pointer), but for passing a 2d array, you would need a pointer to array of int. Did you test that snippet? I assume it doesn't do what you want.
With C99 and above (assuming the compiler supports VLA, variable length arrays), something like this would be correct:
void function( int arr_size_x, int arr_size_y, const int (*array)[arr_size_y]){
As for your idea with a struct, you could only do it when you keep the second dimension fixed. A C array is contiguous in memory, so to do the indexing correctly, the compiler must know all dimensions except for the first one at compile time. VLAs are an exception to that rule, but you can't declare a VLA statically.
What you can do however is using a flat array and do the 2d indexing yourself, like in this tiny example:
struct outputdata
{
size_t rows;
size_t cols;
int *data;
};
const int a_data[] = {1, 2, 3, 4, 5, 6};
const struct outputdata a = {
.rows = 2,
.cols = 3,
.data = a_data
};
// [...]
void function(const struct outputdata x)
{
for (size_t r = 0; r < x.rows; ++r)
{
for (size_t c = 0; c < x.cols; ++c)
{
printf("%d ", x.data[r*x.cols + c]);
}
}
}
I need to find the length of an array, how would I do this without using the sizeof function.
eg if
Array 1 = [0 1 2 3 4 5 6]
the size of this array would be 7.
If you can't use sizeof (tell us why, please), you can use a loop and a sentinel (-1 or some number that can not be used in the array):
int arr[] = {0, 1, 2, 3, 4, 5, 6, -1};
int count = 0;
while (arr[count] != -1) count++;
Many high-level programming language save the length of an array once it is created.
/* e.g. Java */
int[] foo = new int[10];
assert(foo.length == 10);
But the length of an array is not saved in C! This is useful as you can decide how you want to save the length with respect to optimization. You basically have three possibilities to get/save the length:
mark the end of the array with a certain value (i.e. \0 is used for strings)
char foo[] = "bar";
/* foo has length 4(sic!) as '\0' is automatically added to the end*/
int i = 0;
while(foo[i] != '\0'){
printf("%c",foo[i]);
i++;
}
save the length of the array in a variable
int foo[] = {1,2,3,4};
int length = 4;
for(int i = 0; i < length;i++){
printf("%i, ",foo[i]);
}
use sizeof (warning: sizeof is (mostly) computed at compile time and its use is restricted. you can only use sizeof within the function where the array has been created. when you pass an array to a function you only pass the pointer to the first element. therefore you can loop through this array as you know what offset must be used(type of its elements), but you do not know how big it is unless you also passed the length or added a sentinel value)
/* ok */
int foo[] = {1,2,3,4};
for(int i = 0; i < sizeof(foo)/sizeof(int);i++){
printf("%i, ",foo[i]);
}
/* not ok */
void foo(int bar[]);
void foo(int bar[]){
for(int i = 0; i < sizeof(bar)/sizeof(int);i++){
printf("%i, ",bar[i]);
}
}
int main()
{
int arr[] = {1,2,3,4};
foo(arr);
return 0;
}
I have been stuck on this for a while and nothing seems to work.
I have a data structure:
DATA
{
int size;
int id;
}
And I have an array of DATA structures:
myArray = (DATA *) malloc(10 * sizeof(DATA));
Then I assign some test values:
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
So my starting array should look like:
5,9,1,3,0,0,0,0,0,0
Then, I call qsort(myArray,10,sizeof(DATA),comp)
Where comp is:
int comp(const DATA * a, const DATA * b)
{
return a.size - b.size;
}
And trust me, I tried many things with the compare function, NOTHING seems to work. I just never get any sorting that makes any sense.
So my starting array should look like 5, 9, 1, 3, 0, 0, 0, 0, 0, 0.
No, it really won't, at least it's not guaranteed to.
If you want zeros in there, either use calloc() to zero everything out, or put them in yourself. What malloc() will give you is a block of the size required that has indeterminant content. In other words, it may well have whatever rubbish was in memory beforehand.
And, on top of that, a and b are pointers in your comp function, you should be using -> rather than . and it's good form to use the correct prototype with casting.
And a final note: please don't cast the return from malloc in C - you can get into problems if you accidentally forget to include the relevant header file and your integers aren't compatible with your pointers.
The malloc function returns a void * which will quite happily convert implicitly into any other pointer.
Here's a complete program with those fixes:
#include <stdio.h>
#include <stdlib.h>
typedef struct {int size; int id;} DATA;
int comp (const void *a, const void *b) {
return ((DATA *)a)->size - ((DATA *)b)->size;
}
int main (void) {
int i;
DATA *myArray = malloc(10 * sizeof(DATA));
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
for (i = 4; i < 10; i++)
myArray[i].size = 0;
qsort (myArray, 10, sizeof(DATA), comp);
for (i = 0; i < 10; i++)
printf ("%d ", myArray[i].size);
putchar ('\n');
return 0;
}
The output:
0 0 0 0 0 0 1 3 5 9