integer array initialization error in C - c

I'm trying to initialize my array in the following way but get an expression syntax error:
int LineOne[ARRAY_LENGTH];//where ARRAY_LENGTH is a constant of length 10
if(SOME_CONDITION_IS_TRUE){
LineOne[ARRAY_LENGTH] = {0,1,0,0,1,1,1,0,1,1};
}

It really depends on the rest of the code (how you want to use the array), what solution is the best. One other way to do it could be...
int* LineOne = 0;
if(SOME_CONDITION_IS_TRUE) {
static int* init = {0,1,0,0,1,1,1,0,1,1};
LineOne = init;
}

You cannot have array literals in "classic" C, except as initializers when the variable is being defined.
In C99, you can use compound literals to do this, but you must repeat the type in a cast-like expression before the literal:
LineOne = (int[ARRAY_LENGTH]) { 0,1,0,0,1,1,1,0,1,1 };

You can not do it that way. You could use an alternate array and copy it:
#include <string.h>
…
int values[] = {0,1,0,0,1,1,1,0,1,1};
int LineOne[ARRAY_LENGTH];//where ARRAY_LENGHT is a constant of length 10
if(SOME_CONDITION_IS_TRUE)
memcpy(LineOne, values, sizeof(values));

Related

variable sized object may not be initialized even after using const for the variable

I use the const for assigning the variable but the array shows an error "variable-sized object may not be initialized"
#include <stdio.h>
int main()
{
const int city=10;
const int week=2;
int arr[city][week]={34,34,64,23,65,22,65,77,42,74,22,88,46,34,77,53,63,457,234,723};
for(int i=0;i<city;i++)
{
for(int j=0;j<week;j++)
{
printf("%d",arr[city][week]);
}
}
}
You are using const qualified variables for your array dimension and not "integer constant expressions". For C, this means that your array is a variably modified type, for which C does not allow initializers.
As others already told you, if initialization would be allowed, the syntax has to be = and not ==.
You have several issues.
you've posted it in the subject, is that you can't use const int for the array length and then initialize it, because it will become a variable-sized object, and you can't initialize it in with constant numbers. You can use #ifdef to define city/week, and then it will not happen.
You've used compare (==) instead of assignment (=)
change:
int arr[city][week]=={34,34,64,23,65,22,65,77,42,74,22,88,46,34,77,53,63,457,234,723};
to:
int arr[city][week]={34,34,64,23,65,22,65,77,42,74,22,88,46,34,77,53,63,457,234,723};
you need to change your printf and probably add line break:
printf("%d\n",arr[i][j]);
so to summarize:
#include <stdio.h>
#define city 10
#define week 2
int main()
{
int arr[city][week]={34,34,64,23,65,22,65,77,42,74,22,88,46,34,77,53,63,457,234,723};
for(int i=0;i<city;i++)
{
for(int j=0;j<week;j++)
{
printf("%d\n", arr[i][j]);
}
}
}
== compares, = assigns
you even would print the same output
i would also prefer to use {a,b},{c,d}...

initializing array of structure with array elements in it

#include <stdio.h>
int main()
{
typedef struct s
{
int a;
int b[5];
char c[2];
}st;
st vs[1];
vs[0] = {1,{1,2,3,4,5},{'c','d'}};
printf("%d:a\n",vs[1].a);
printf("%d:b[0]\t %d:b[4]\n",vs[0].b[0],vs[0].b[4]);
printf("%c:c[0]\t %c:c[1]\n",vs[0].c[0],vs[0].c[1]);
return 0;
}
why does this doesn't work?
on
gcc -o main *.c
I get this error
main.c: In function 'main':
main.c:15:12: error: expected expression before '{' token
vs[0] ={1,{1,2,3,4,5},{'c','d'}};
But if I have this:
#include <stdio.h>
int main()
{
typedef struct s
{
int a;
int b[5];
char c[2];
}st;
st vs[] = {
{1,{1,2,3,4,5},{'c','d'}}
};
printf("%d:a\n",vs[0].a);
printf("%d:b[0]\t %d:b[4]\n",vs[0].b[0],vs[0].b[4]);
printf("%c:c[0]\t %c:c[1]\n",vs[0].c[0],vs[0].c[1]);
return 0;
}
it works. What is the logic in this.
How can I make it work using st vs[1] method?
You can only do braced initialization when you declare a variable. So,
st vs[] = {
{1,{1,2,3,4,5},{'c','d'}}
};
is allowed. But
vs[0] = {1,{1,2,3,4,5},{'c','d'}};
is not. Because this is not a initialization but assignment.
However, you can use C99's compound literal, see C11, 6.5.2.5:
vs[0] = (struct s){1,{1,2,3,4,5},{'c','d'}};
Initialization is when you declare a variable and provide initial values for it as part of the declaration. For example this is legal:
st vs[1] = { {1,{1,2,3,4,5},{'c','d'}} };
Your code is actually attempting assignment. Assignment is when an existing variable has a value assigned to it. The reason your code doesn't work is that {1,{1,2,3,4,5},{'c','d'}} isn't a value.
In a statement (not a declaration), each expression must be readable by the compiler on its own merit, and a more complicated statement is made up of various expressions joined by operators. So the compiler doesn't know what to do with {1,{1,2,3,4,5},{'c','d'}} - at this stage it has no idea that that is supposed to be a st.
Since C99 there is a new language construct you can use here, called compound literal:
vs[0] = (const st){1,{1,2,3,4,5},{'c','d'}};
Note that this is not a cast operator being applied to some sort of braced expression; it is a single syntactic construct (Typename){ initializers } .
My use of const is a micro-optimization, it may help the compiler store the literal in a read-only block of the executable and allow constant folding.

Initialize array after declaring in C

I am trying to do the following but am getting the following error:
"error: expected expression before { token
Test_Stubs.h
#define SIGNATURE 0x78,0x9c
Test.c
#include "Test_Stubs.h"
static unsigned myArray[100];
static void
setup(void)
{
myArray = {SIGNATURE};
}
EDIT
Follow on question:
Is there a way to assign the individual values in the #define to specific indexes of myArray? For instance...
#include "Test_Stubs.h"
static unsigned myArray[100];
static void
setup(void)
{
myArray[0] = SIGNATURE[0]; //0x78
myArray[1] = SIGNATURE[1]; //0x9c
}
Clearly the above code will not code as SIGNATURE is neither an array or pointer.
As per the C syntax rules, you can only initialize an array using a brace enclosed initializer list at the time of definition.
Afterwards, you have to initialize element by element, using a loop, or, if you need to initialize all the elements to the same value, you can consider using memset().
EDIT:
No, as I mentioned in my comments, as per your code snippet, SIGNATURE is neither an array name, nor represent any array type, so you cannot use indexing on that.
However, using compound literal (on and above C99), if you change your #define, then, somehow, you can make this work. See the below code for example,
#include <stdio.h>
#define SIGNATURE ((unsigned [100]){0x78,0x9c})
static unsigned myArray[100];
int main (void)
{
myArray[0] = SIGNATURE[0]; //0x78
myArray[1] = SIGNATURE[1]; //0x9c
return 0;
}
See a LIVE VERSION

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]);
}

Create a C function that accepts parameters of different data types

I'm relatively new to the C programming language, and I'm trying to figure out how to create a function that can accept different types of data as parameters. The function is supposed to count and return the number of elements in a character or integer array. I already have two separate functions that will do this, but I would really like to be able to use one function for both tasks. Is there a way to do this in C?
Thanks in advance!
There is no standard function overloading in C (nor are there templates), but you could probably look into "printf-like" functions (or variadic functions) and maybe they can do what you need. If anything they allow for a flexible parameter list.
There is an example here of such a function that takes a variable size integer array.
Perhaps you could have a function signature such as void iterate(const char* format, ...); that you use in the following ways:
iterate("char", some_char_array); // for char arrays/strings
Or
iterate("int", some_int_array); // for integer arrays
Aniket makes a good point though, how do you count the elements in an integer array? If you pass an int array as an argument, you would need to pass the size too which defeats the purpose of counting the elements in the array (as you already know that i.e. the size).
I assume you don't know the size but you have a terminator value in the array (such as -1).
I've hacked something quick that kinda does what you need with the above assumption in mind.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int iterate(const char* format, ...)
{
va_list ap;
va_start(ap, format);
if (strcmp(format, "char") == 0)
{
char* array = va_arg(ap, char*);
va_end(ap);
return strlen(array);
}
else if (strcmp(format, "int") == 0)
{
int j = -1;
int* int_array = va_arg(ap, int*);
while (int_array[++j] != -1)
;
va_end(ap);
return j;
}
va_end(ap);
return 0;
}
int main()
{
printf("%d\n", iterate("char", "abcdef"));
int arr[] = {5, 4, 3, 2, 1, 0, -1};
printf("%d\n", iterate("int", arr));
return 0;
}
This prints:
$ ./a.out
6
6
So, let's assume your two functions are called sizeof_char_array and sizeof_int_array.
In C11, there is a new feature called "generic selection" that will let you do what you want with a relatively simple macro:
#define sizeof_array(X) \
_Generic (*(X), \
char: sizeof_char_array, \
default: sizeof_int_array) (X)
(I don't even have a C11 implementation to test this against, so caveat emptor!)
Prior to C11, this was sometimes accomplished with a macro using regularly named functions. You can define a macro that will call one function or the other depending on a macro argument hint:
#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)
int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";
sizeof_array(int, a); /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b); /* macro expands to sizeof_char_array(b) */
If the input argument is truly an array, you can use a macro to compute its size directly:
#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))
In the case of an array, the following expression is true:
(void *)arr == &arr
Because the address of an array has the same location in memory as the address of its first element.
So, the macro computes: sizeof(arr)/sizeof(arr[0]). Since the sizeof operator reports the size in bytes of its argument, the computed expression results in the number of elements in the array. However, if you are using a sentinel to compute the length, the ARRAY_SZ macro will result in a size at least one larger than the length found traversing the array for the sentinel.
In the case that the argument is not an array, then the expression results in a divide by 0 exception.
The answer is quite simple. You do need a function for this task. Just try this piece of code
#define len(array) sizeof(array)/sizeof(*array)
and that's it.
Important note: As pointed out in the comments, this will not work for dynamically allocated arrays.
You should make your function arguments take in a void * type. This way, you can pass in different types of data, and type-cast it to the one you want. However, you do need to watch out because there is no guaranteed way to correctly 'guess' the type that a void* points to.
In either case, you will need some sort of type-inferencing system to tell the C compiler which function to call. Which means, you will need to know, before-hand the type of array you might send in as a parameter to this "super function" of yours.
There is no "auto-type-inferencing" in C that can let you reflect upon the type of data at runtime. Better yet, you might have to write your own runtime environment for this to happen.
A slightly trivial hackish way to do this:
#include <stdio.h>
size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes)
{
return sizeOfTheArrayInBytes/sizeOfOneElementInArray;
}
int main(int argc, char *argv[])
{
char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'};
int iArr[5] = {10,20,30,40,50};
printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)),
GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr)));
return 0;
}
It's not really possible, but you can make a tagged union
typedef struct {
union {
ssize_t i;
double d;
char *s;
} unknown;
char identity;
} Dynamic;
Or you can use a void pointer:
typedef struct {
void *unknown;
char identity;
} Dynamic;

Resources