Multiple ways to initialize arrays in c programming - c

In how many ways we can declare an array in C programming? if there are many ways to declare an array in C, what are the best practices or best way among?
So far I have been initializing an array like this:
int myArray[SIZE] = {1,2,3,4....};
What are the other ways do the same?

From C99, you can also use explicit indexes, called designators, in the initializer expression, which is sometimes very nice:
const int threetoone[] = { [2] = 1, [1] = 2, [0] = 3 };
The above is the same as
const int threetwoone[] = { 3, 2, 1 };

datatype arrayName[arraySize];
int x[10];
int x[]={1,2,3,4,5,6,7,8,9,0};
you can look at this question for more details on ways to initialize an array in C
declaring-and-initializing-arrays-in-c

Related

Is it a good practice to group related constants using structs in C?

I was wondering if it would be a good idea to use structs as pseudo namespaces (à la C++) to group constants which are functionally or conceptually related to each other.
static const struct {
const unsigned int START;
const unsigned int END;
} COUNTER = {.START = 1, .END = 100};
Is there any downside to this? If not, is it redundant (or maybe even unconvenient) to have both the struct instance and its members declared as const? Where should the constantness of these values be stated?
I was wondering if it would be a good idea to use structs as pseudo namespaces
Well, it CAN be a good idea. It's not intrinsically bad. An argument against is that if you feel that you need namespaces, then it's likely that C is the wrong language in the first place. But it can be used this way, and it is sometimes used this way.
Where should the constantness of these values be stated?
It's in general enough to declare the whole struct as const. But beware with pointers. This code is valid and will print "42":
int x = 5;
const struct {
int *p;
} S = {.p = &x };
int main()
{
*(S.p) = 42;
printf("%d\n", x);
}
In the above code, you are not allowed to change S.p so that it points to something else, but there is a difference between a const pointer and a pointer to const. So for pointer, it could be a good idea to add an extra const.
To clarify, the pointer p will be declared like it was a int * const p which means you cannot change the pointer itself, but in order to protect the data it's pointing to, you need const int *p. To get both, use const int * const p, but if the struct is declared as const, you'll get one of them "for free" so const int *p is enough to get both.
And if you consider pointers to pointers, well, think it through for a long time and test it to make sure it works the way you want.
From comments:
Why not enums?
Because this is not valid:
enum S {a = 5};
enum Y {a = 6};
The compiler will tell you that a is already defined. So enums is not good for emulating namespaces. Also, you cannot use enums for non-integers.
Is it a good practice to group related constants using structs in C?
It's opinion based. If it works for you, do it.
I wouldn't do like that i C. Instead I use #define
Like:
#define GROUPNAME_NAME
so in your case I would do
#define COUNTER_START 1
#define COUNTER_END 100
In C++ I would do:
const unsigned int COUNTER_START = 1;
const unsigned int COUNTER_END = 100;
The difference between C and C++ is due to differences in language specification.

How to assign 1D array to a 2D array?

I have a 1D array A[3] & a 2D array B[4][3]. I want to assign the array A[3] to one of the rows of array B[4][3]. How to do it correctly?
#include<stdio.h>
void main()
{
int A[3]={1,2,3};
int B[4][3]={0};
int row_select=2;
B[row_select][] = A;
}
But this assignment doesn't work. I don't want to assign element by element using a for loop. I want to do it in one statement.
memcpy could be a good option, although it's very likely it uses a loop internally.
memcpy(B[row_select], A, sizeof(A));
Don't Do This: Use memcpy
There is a way to do the assignment with a single statement, as long as you are willing to do some preliminary setup to render your code illegible. Your can use the fact that structures can (1) be assigned to each other in one step, and (2) contain fixed-size arrays. The compiler will probably run memcpy under the hood anyway, but it's a fun exercise in ridiculousness:
#include<stdio.h>
#define SZ 3 // this is just for convenience
// a pointer to an anonymous structure containing our array
typedef struct {
int x[SZ];
} *pthrowaway;
int main(void)
{
int A[SZ]={1,2,3};
int B[4][SZ]={0};
int row_select=2;
pthrowaway a = (pthrowaway)&A;
pthrowaway b = (pthrowaway)&B[row_select];
*b = *a; // magic
return 0;
}
The variables a and b are unnecessary. You can actually assign the arrays in a single statement:
*(pthrowaway)&B[row_select] = *(pthrowaway)&A;
Here is an IDEOne link showing the C99 version: https://ideone.com/IQ6ttg
And here is a regular C one: https://ideone.com/pH1hS2

Variable character inside a constant

Having defined this:
int var1 = 1;
int var2 = 2;
int var3 = 3;
I want to make this:
int result = varc * 70; // Where c is a previously defined int that can take 1,2 or 3 value.
Solutions? Thank you.
In C you're out of luck on this since it's not a reflective language. That is you can't get the value of a variable by somehow "stringifying" the name you gave it in the source code.
But what you could do is use an array:
int vars[] = {1, 2, 3};
int result = vars[i] * 70;
where i is 0, 1, or 2.
you write:
int result = varc * 70;
This is what you want to make is not possible in language c.
Note: varc is an identifier
Remember IDENTIFIER in C :
Identifiers are names for entities in a C program, such as variables, arrays, functions, structures, unions.
It must be unique for all entities and also an identifier is a string of alphanumeric characters
Ok, you remembered. :)
So, you never used "c" present in "varc" to treat(refer) to other variables/identifies/entities.
I hope I might be solve your doubt in easiest way .Thank you! :)

Initializing multidimensional arrays in C

I'm just a tad confused about initializing multidimensional arrays in C...
This works:
int foo[2][MAX] = {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
But this does not:
int foo[2][MAX];
foo = {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
How come?
This syntax is for initialization, but in the second case you are using it for assignment which will not work.
type varName = someValue; // this is declaration and initialization
type varName; // this is declaration
varName = someValue; // this is assignment and not initialization
That is initialization can only be done at the declaration time, else it's a normal assignment.
The { syntax is only valid when you're initializing and declaring an array at the same time.
After declaring it, you need to use the complete syntax:
foo[0][0] = 2;
Technically speaking, C only has one-dimensional arrays. You create multidemnsional arrays by making arrays of arrays. The name of an array is converted to a pointer to its first element, and only the outer array is converted to a pointer. It's a pointer to an array of MAX ints, or int(*)[MAX].
As you said, this syntax is used to initialize an array, but in your second piece of code:
int foo[2][MAX];
Here, foo is uninitialized, and then
foo = {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
This is assignment, not initialization.
Multidimensional or not, arrays in C are not copyable, which means that there's no way to assign anything to the entire array using core language features after the initialization is complete.
However, it is still possible to copy arrays by using memcpy function. In combination with compound literals it allows you to do what you tried to do. You just have to use a different syntax
int foo[2][MAX];
memcpy(
foo,
(int[2][MAX]) {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
},
sizeof foo);
In C99 (or in gcc as an extension) you can make use of compound literals:
int (*foo)[MAX];
foo = (int [][MAX]) {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
But note that foo must be declared as a pointer to MAX int's (not as a 2D array)
You have misunderstood the concept of 'initialization' and 'assignment`.
For example
int a = 10; // Initialization
Initialization is nothing but declaration + assignment.
But
int a; // Declaration
a = 10; // Assignment
When you do like this-
int foo[2][MAX] = {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
internally it came to know 2 rows and MAX columns. It will initialize the whole array.
But-
int foo[2][MAX];
foo = {
{2,4,34,43,23,0},
{2,4,34,43,23,0}
};
Here foo represent the starting address of the array. Here you are trying to assign the values to 2D array. when you are trying to assign values to array it doesn't know how many rows and how many columns are there. so it is not possible and not allowed.
When you want to assign the input to array A better solution is scan it from user/ at run time-
int foo[2][MAX],i,j;
for(i=0;i<2;i++){
for(j=0;j<max;j++)
scanf("%d",&foo[i][j]);
}

Copying an array in a designated initializer

I'm trying to initialize a const struct with a designated initializer. However, one of the struct elements is a fixed-width array. I already have the contents I would like to initialize the array with in another fixed-width array of appropriate size.
Is there any way to do this with a designated initializer? A simple (failing example) of what I'm trying to accomplish is demonstrated below.
struct foo {
uint8_t array1[4];
uint8_t array2[4];
}
uint8_t array[4] = {
1, 2, 3, 4
};
struct foo const bar = {
.array1 = array, // incompatible pointer to integer conversion
.array2 = { *array } // only copies the first element
};
Short answer: you can't. C does not copy arrays (without the use of (standard library-)functions). The warnings come from the fact that you cannot assign an array as a whole, even when they are static or constant. When an array is used as an r-value in an assignment it decays to a pointer and thus cannot be assigned to another array (as a whole).
The easiest way to go would be to use memcpy, but obviously that must be inside a function.
If bar has global scope, or is declared static, then you won't be able use designated initializers to initialize from non-immediate values, regardless of whether or not the members in question are arrays.
However, if:
bar is declared on the stack of some function, and
Your fixed-size array really does only have 4 elements,
then you might be able to get away with something like this:
#include <stdio.h>
#include <stdint.h>
struct foo {
uint8_t array1[4];
uint8_t array2[4];
};
#define ARRAY_INIT(a) { a[0], a[1], a[2], a[3] }
int main (int argc, char **argv) {
uint8_t arr_init[4] = {
1, 2, 3, 4
};
struct foo const bar = {
.array1 = ARRAY_INIT(arr_init),
.array2 = ARRAY_INIT(arr_init),
};
printf("%d, %d\n", bar.array1[0], bar.array2[3]);
return (0);
}
The initializer array must appear before what is being initialized in the stack frame. Or it may come from a function parameter.
Of course if your array is much bigger than this, then using a macro like this will get very messy indeed.
While you may not be able to initialize the array by copying from another array, it may be helpful to use a preprocessor macro:
#define ARRAY_INIT {1, 2, 3, 4}
struct foo const bar = {
.array1 = ARRAY_INIT,
.array2 = ARRAY_INIT
};

Resources