Global Variable Array in C - c

I'm trying to create a global array whose size is determined by an external parameter file at runtime.
I've seen other questions on this and tried:
int const Nt=1280;
double *Array = NULL;
Array = malloc(Nt * Nt * sizeof(double));
However, I get errors such as:
Error: Conflicting types for Array
Error: Initializer element is not constant
How can I create such a global array without needing to recompile every time I need to change its size?

Assignment is not allowed at global scope. You have to do it in a function instead.
int const Nt = 1280;
double *Array = NULL;
Assuming the above 2 statements are at global scope. They are examples of initialization because the statements assign value at the declaration itself. This is allowed at global scope and the initializers can be constant values, string literals or other variables accessible at this point.
const int Nt ; // Just declaration
Nt = 1280 ; // Error. Assignment is not allowed at global scope.
const char* myName = "CHP" ;
int a[] = { 11,22,33,44,55 } ;
And similarly in your example Array is just a declaration. Do the assignment in a function.
void assignArray() {
Array = malloc(Nt * Nt * sizeof(double));
// ...
printf("%d", sizeof(Array)/sizeof(Array[0]); // Size which is nothing but Nt*Nt
// 0 to (Nt * Nt) - 1
}
And regarding the segmentation fault, post more code.

Global function initializers have to be compiled directly into the executable. Therefore, they cannot contain any information that changes at runtime, and they cannot contain function calls. And the initializers must be in the same statement as the declaration.
WORKS:
int x = 1;
DOESN'T WORK:
int x;
x = 1;
You should move your initializer into a function if you can't fit it within those rules.

Do the initialization in a function (e.g. in main()):
int main() {
Array = malloc(dim1 * dim2 * sizeof(double));
...
}

double *Array = NULL;
This is fine (as long as you've included a header that defines NULL before you write it).
Array = malloc(dim1 * dim2 * sizeof(double));
You say this yields:
Error: Conflicting types for Array
Error: Initializer element is not constant
That is because the compiler is bending over backwards to accept your code, and manages to interpret the Array as an 'implicit int' variable, as if you wrote:
int Array = ...
Since int is not the same as double *, it gives you the conflicting types error.
The second message tells you that the initializer - the call to malloc() - is not a constant, and initializers outside functions must be constants. If you placed the line inside a function, then you'd have an assignment (not an initializer), and the code would be OK, though better written as:
if (Array == NULL)
Array = malloc(dim1 * dim2 * sizeof(double));
You should be compiling with more stringent compilation warnings. I get:
$ cat x.c
#include <stdlib.h>
double *Array = NULL;
Array = malloc(23 * 37 * sizeof(double));
$ gcc -g -std=c99 -pedantic -Wall -Werror -c x.c
x.c:3:1: error: data definition has no type or storage class [-Werror]
x.c:3:1: error: type defaults to ‘int’ in declaration of ‘Array’ [-Werror]
x.c:3:1: error: conflicting types for ‘Array’
x.c:2:9: note: previous definition of ‘Array’ was here
x.c:3:9: error: initialization makes integer from pointer without a cast [-Werror]
x.c:3:1: error: initializer element is not constant
cc1: all warnings being treated as errors
$

Related

C - subscripted value is neither array nor pointer nor vector

I declared an array and pass a 2D array as a parameter. However I keep getting the same error: subscripted value is neither array nor pointer nor vector.
for this line: vertex[i][j-1] = shape[i][j];
How can I solve it?
header file:
GLfloat mijnplayer [][4] ={
{0,-0.091057,0.198079,0.084590},
{0,-0.158043,0.158043,0.071039},
{0,-0.071039,0.158043,0.158043}};
function call:
int main(void)
{
drawVertex(mijnplayer,3,1);
}
void drawVertex(GLfloat shape[][4], int numberVertex, int shape)
{
int i,j;
GLfloat vertex[][3]={0};
//convert 4element array to 3 element array
for(i=0;i<numberVertex;i++)
{
for(j=1;j<4;j++)
{
vertex[i][j-1] = shape[i][j];
}
}
for(i=0;i<numberVertex;i++)
{
glVertex3fv(vertex[i]);
}
}
EDIT:
the complete compiler output:
cc -c -o mijnTest.o mijnTest.c
mijnTest.c:23:59: error: conflicting types for ‘shape’
void drawVertex(GLfloat shape[][4], int numberVertex, int shape)
^
mijnTest.c:23:25: note: previous definition of ‘shape’ was here
void drawVertex(GLfloat shape[][4], int numberVertex, int shape)
^
mijnTest.c: In function ‘drawVertex’:
mijnTest.c:43:26: error: subscripted value is neither array nor pointer nor
vector
vertex[i][j-1] = shape[i][j];
^
mijnTest.c: In function ‘drawScene’:
mijnTest.c:69:2: warning: passing argument 1 of ‘drawVertex’ from
incompatible pointer type [enabled by default]
drawVertex(assen,6,0);
^
mijnTest.c:23:6: note: expected ‘GLfloat ()[4]’ but argument is of type
‘GLfloat ()[3]’
void drawVertex(GLfloat shape[][4], int numberVertex, int shape)
^
make: *** [mijnTest.o] Error 1
Its because shape is an variable of data type int and its neither array nor pointer nor vector.
Either you got the data type wrong or you are just using the wrong variable.
A declaration like
GLfloat vertex[][3]
is only valid as a function argument (and then it's equal to GLfloat (*vertex)[3]). If you declare an array as a local or global variable, you must give it a size.
It works when you define mijnplayer because then the compiler can deduce the size from the data you use for initialization (the size is set implicitly). If you don't do it then the compiler can't know what size the array is, and you need to specify it explicitly.

different initializ and sign pointer value in global and function

I know I will get many down grade regarding this question, but I still write following test code:
int *gPtr;
//I know I can NOT write below code line, but I need know WHY
gPtr = NULL;//or some other value which I want to init it
//int *gPtr = NULL; //this line should be OK
int main (void)
{
int *ptr;
ptr = NULL;
return 0;
}
The global *gPtr during compile will output error:
ptr.c:4:1: warning: data definition has no type or storage class [enabled by default]
ptr.c:4:1: error: conflicting types for ‘gPtr’
ptr.c:3:6: note: previous declaration of ‘gPtr’ was here
ptr.c:4:8: warning: initialization makes integer from pointer without a cast [enabled by default]
However, in the function, I did same code, but no compile error/warning, I would like to know:
what is the different between sign a value in global and function.
why compiler do NOT allow me sign value in global area.
what is different between int a = 0; and int a; a=0;//no other code between these two sentences
please give me advise for above three questions according to the compiler view(or you think it should have other explanation in some others view like coding standard?)
You can define a global variable with an initial value:
int *gPtr = NULL;
But you cannot do an assignment outside of a function scope.
The compiler (well, at least my clang compiler) actually interprets
gPtr = NULL;
in the global scope as
int gPtr = NULL;
which causes similar warnings and a conflicting types error:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
gPtr = NULL;
^~~~
error: redefinition of 'gPtr' with a different type: 'int' vs 'int *'
note: previous definition is here
int *gPtr;
Global variable without an explicit initial value are automatically initialized
to zero, therefore in your case
int *gPtr;
would be sufficient (as #WhozCraig already commented above).
This compiles fine:
#include <stdio.h>
/* int *gPtr; */
/* gPtr = NULL; */
int *gPtr = NULL;
int main (void)
{
int *ptr;
ptr = NULL;
return 0;
}
I suspect you had one of two problems. Firstly, you can't declare gptr, then assign NULL to it, and then do a int *gptr = NULL (which does the first two combined); hence I commented out the first two. You need one or the other. Secondly your line int *gPtr = NULL; was missing a semicolon.

Struggling with compiliation: Pointers in C

I've been programming in java for over a year now but am slowly teaching myself C / objectiveC whilst studying at uni from the book: Cocoa and Objective C - Up and Running. I'm still going through the introductory chapters familiarising myself with syntactical differences in C with java and have come across a section on dynamic memory, specifically on pointers. The example it provides is this:
#include <stdio.h>
#include <stdlib.h>
int* numbers;
numbers = malloc ( sizeof(int) * 10);
//create a second variable to always point at the
//beginning of numbers memory block
int* numbersStart;
numbersStart = numbers;
*numbers = 100;
numbers++;
*numbers = 200;
//use the 'numbersStart' variable to free the memory instead
free( numbersStart );
I understand the code - create an integer pointer, allocate 10 blocks of memory for it, create a second pointer to point at the first dynamic memory block of numbers, set the first block to 100, increment to the 2nd block and set that to 200, then use free() to free memory.
However, when I try to compile I get a series of errors. The code is saved in a c class called Dynamic.c in a folder called dynamic.
here is a print of what occurs in terminal:
gcc Dynamic.c -o Dynamic
Dynamic.c:13: warning: data definition has no type or storage class
Dynamic.c:13: error: conflicting types for ‘numbers’
Dynamic.c:12: error: previous declaration of ‘numbers’ was here
Dynamic.c:13: warning: initialization makes integer from pointer without a cast
Dynamic.c:13: error: initializer element is not constant
Dynamic.c:15: warning: data definition has no type or storage class
Dynamic.c:15: error: conflicting types for ‘numbersStart’
Dynamic.c:14: error: previous declaration of ‘numbersStart’ was here
Dynamic.c:15: error: initializer element is not constant
Dynamic.c:16: warning: data definition has no type or storage class
Dynamic.c:16: warning: initialization makes pointer from integer without a cast
Dynamic.c:17: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘++’ token
Dynamic.c:18: warning: data definition has no type or storage class
Dynamic.c:18: error: redefinition of ‘numbers’
Dynamic.c:16: error: previous definition of ‘numbers’ was here
Dynamic.c:18: warning: initialization makes pointer from integer without a cast
Dynamic.c:19: warning: data definition has no type or storage class
Dynamic.c:19: warning: parameter names (without types) in function declaration
Dynamic.c:19: error: conflicting types for ‘free’
/usr/include/stdlib.h:160: error: previous declaration of ‘free’ was here
If someone could explain why these errors occur I would be much obliged, I don't see why they should be as its an example from a book.
Thanks.
That program is no good. You need at least a main() function. Add:
int main(void)
{
Right after the #include lines, and add:
return 0;
}
at the very end, and it will compile.
Wrap it in a main() function:
#import <stdio.h>
#import <stdlib.h>
int main()
{
int* numbers;
numbers = malloc ( sizeof(int) * 10);
//create a second variable to always point at the
//beginning of numbers memory block
int* numbersStart;
numbersStart = numbers;
*numbers = 100;
numbers++;
*numbers = 200;
//use the 'numbersStart' variable to free the memory instead
free( numbersStart );
return 0;
}
You need to define a main function:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int* numbers;
numbers = malloc ( sizeof(int) * 10);
...
free( numbersStart );
return EXIT_SUCCESS;
}
numbers = malloc ( sizeof(int) * 10);
This is a statement and you cannot have a statement outside of a function in C.
Organize your program with functions and put the statements in the functions body. This is correct:
// This defines a function named foo that takes no argument and returns no value
void foo(void)
{
int* numbers;
numbers = malloc ( sizeof(int) * 10);
//create a second variable to always point at the
//beginning of numbers memory block
int* numbersStart;
numbersStart = numbers;
*numbers = 100;
numbers++;
*numbers = 200;
//use the 'numbersStart' variable to free the memory instead
free( numbersStart );
}

How to initialize array of pointers to functions?

I have following code:
typedef int (*t_Function) (int x);
t_Function Functions[MAX_FUNCTIONS];
int f(int x)
{
return 0;
}
But I cannot initialize it properly. If I add following line:
Functions[0] = f;
then compiler generates following error:
prog.c:217: warning: data definition has no type or storage class
prog.c:217: error: conflicting types for Functions
How to initialize this array of pointers to functions?
You should either do it inside a function, where Functions[0] = f; works fine, or with an array initializer:
t_Function Functions[MAX_FUNCTIONS] = {f};
For this to work, f (and all functions you want in Functions) must have been declared at the point where this definition appears. Note that all other MAX_FUNCTIONS-1 elements of Functions will be NULL automatically if at least one of them is filled this way.

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