Initialize array after declaring in C - 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

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}...

multiple definition and making sure function is correctly written

This is my .h file
#ifndef _test_h_
#define _test_h_
void new_cmd(void);
void open_cmd(void);
void close_cmd(void);
void close_all_cmd(void);
void save_cmd(void);
void save_as_cmd(void);
void save_all_cmd(void);
void print_cmd(void);
void exit_cmd(void);
void call(char *cmd_name);
struct {
char *cmd_name;
void (*cmd_pointer)(void);
} file_cmd[] =
{
{"new", new_cmd},
{"open", open_cmd},
{"close", close_cmd},
{"save", save_cmd},
{"save as", save_as_cmd},
{"save all", save_all_cmd},
{"print", print_cmd},
{"exit", exit_cmd}};
#endif
This is my function file
void call(char *cmd_name){
int i;
scanf("Enter command: %c\n",cmd_name);
for(i = 0; i < sizeof(file_cmd); i++){
if(strcmp(cmd_name, file_cmd[i].cmd_name) == 0){
file_cmd[i].cmd_pointer();
}
}
I just deleted all file_cmd functions because it seems for other people
and this is my main file
#include <stdio.h>
#include <string.h>
#include "test.h"
int main(void){
char cmd;
call(cmd);
return 0;
}
More I want to know is that my function void call is correctly written.
when I try to compile, it says
expected 'char*' but argument is of type 'char'
multiple definition of 'file_cmd'
first define here.
I am so confused how to fix it.
Please help
thank you.
You have two very different errors that you really should have asked about in two different question, but I'll be nice and answer both anyway.
In the main function you have a variable named cmd. It is of type char. You pass it to the call function, which expects an argument of type char * (i.e. a null-terminated string).
To fix this you first need to make sure that cmd is the correct type (i.e. char * instead of plain char). Secondly you need to make sure this pointer is actually pointing to a valid null-terminated byte string.
In other words, something like this:
char *cmd = "open";
call(cmd);
C really only cares about translation units. A translation unit is a single source files with all included header files.
The problem here is that variables can only be defined in a single translation unit. And since you define the variable file_cmd in a header file that is included in multiple source files, it will be defined in both translation units created from those two source files.
The solution here is to only declare the variable in the header file, and define it in a single source file.
For example, do something like this in the header file
struct command_struct
{
char *cmd_name;
void (*cmd_pointer)(void);
};
extern struct command_struct file_cmd[];
Then in one source file (like your "function file")
struct command_struct file_cmd[] = {
// Your initialization...
};
There are also other problems with your code, some of them will lead to undefined behavior.
For example the sizeof operator returns the size in bytes, not the number of elements in an array. To get the number of elements in an array you need to divide the byte-size of the full array with the byte-size of a single element. For example sizeof file_cmd / file_cmd[0].
Do note that the division only works for real arrays, not pointers, and that arrays very easily decays to pointers (to their first element).

Array size with const variable in C [duplicate]

This question already has answers here:
Can a const variable be used to declare the size of an array in C?
(5 answers)
Closed 4 years ago.
I've found an interesting fact, and I didn't understand how is it works.
The following piece of code just works perfectly.
#include <stdio.h>
int main(){
const int size = 10;
int sampleArray[size];
typedef char String [size];
return 0;
}
Then, I tried to use only and only the constant variable with a global scope, and it's still fine.
#include <stdio.h>
const int size = 10;
int main(){
int sampleArray[size];
typedef char String [size];
return 0;
}
But, if I change the arrays's scope to global as well, I got the following:
error: variably modified ‘sampleArray’ at file scope
#include <stdio.h>
const int size = 10;
int sampleArray[size];
typedef char String [size];
int main(){
return 0;
}
And I didn't get it! If I'd replace the const variable for ex. to #define it'd be okay as well.
I know that the #define variable is preprocessed, and as far as I know the const variable is only read-only. But what does make the global scope after all?
I don't understand what is the problem with the third piece of code, if the second one is just okay.
Variable Length Arrays may have only automatic storage duration. VLAs were introduced in C99.
It is not allowed to declare a VLA with the static storage duration because the size of VLA is determinated at the run time (see below)
Before this Standard you can use either a macro like
#define SIZE 10
//...
int a[SIZE];
or a enumerator of an enumeration like
enum { SIZE = 10; }
//...
int a[SIZE];
By the way you may remove the const qualifier and just write
int size = 10;
instead of
const int size = 10;
(In C++ you have to use the const qualifier though in C++ there are no VLAs except that some compilers can have their own language extensions)
Take into account that the sizeof operator for VLAs is calculated at the run-time instead of the compile-time.

integer array initialization error in 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));

Initialization of a pointer array

I'm facing a problem initializing an array with pointers to members of a structure. The structure members have to be accessed through a structure pointer. The reason for this is we initialize the pointer at runtime to a memory mapped address location. The following code snippet is an example of the problem;
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
long* lp;
}T;
typedef struct
{
long l;
}F;
F* f;
T t[] =
{
{ &f->l }
};
void init (void)
{
f = (F*) 0x08000100;
}
int main (void)
{
init();
return EXIT_SUCCESS;
}
The compiler output is the following;
gcc -O0 -g3 -Wall -c
-fmessage-length=0 -osrc\Test.o ..\src\Test.c ..\src\Test.c:18:
error: initializer element is not constant
..\src\Test.c:18: error: (near initialization for `t[0].lp')
..\src\Test.c:18: error: initializer element is not constant
..\src\Test.c:18: error: (near initialization for `t[0]')
Build error occurred, build is stopped
The problem here is we initialize the pointer at runtime, the compiler doesn't know where it can find the structure members. We cannot work around the structure pointer as we don't wan't to use the linker script for this.
Any ideas how to get around this one?
T t[] =
{
{ &f->l }
};
The address of an element (e.g. &f->l) is only known at run-time.
Such a value cannot be used for compile-time initialization (which is what's being done here).
The t[] array cannot be filled out until runtime - because the address of F isn't known until runtime.
You could initialize T[] to {NULL} and patch it in post-init.
Another approach is to initialize the members of T to just simply be the offset within the structure, and after you init f, to walk through the array and adjust the pointer locations by adding the address of f. This technique is similar to what is often used in linking.
Something like this:
#define MEMBER_OFFSET_OF(a,b) &(((a*)0)->b)
T t[] =
{
{(long*)MEMBER_OFFSET_OF(F, l)}
};
const int numElementsInT = sizeof(t) / sizeof(t[0]);
void init()
{
f = (F*) 0x08000100;
for (int i= 0; i < numElementsInT; i++)
{
t[i].lp += (unsigned int)f;
}
}
Lets imagine that you could use non-constant data to initialize a global: you still have a huge problem.
When t is initialized, f still has an indeterminate value: this happens before init() executes and assigns your magic address. Because of this, even if you could use &f->l, you'd have to reset all places it's been used, anyway.
Technically speaking for a C90 compiler there is no way around this. For the initialization idiom,
declarator = initialization sequence
the initialization sequence needs to be a constant expression, i.e. one which can be computed at compile-time or at link-time. So,
int a;
int *b[] = { &a };
works, while
void foo() {
int a;
int *b[] = { &a };
}
will not because the address of the automatic a isn't computable before runtime.
If you switch to C99, the latter will work. Your code however still is beyond what a C99 compiler can precompute. If you switch to C++ your code would work, at least Comeau doesn't object.
Edit: of course Roger is correct in that this doesn't solve your problem of having an incorrect dereferencing through a NULL pointer.

Resources