ANSI C -> Arrays -> Variably modified at file scope - c

While I'm trying to explore possibilities of arrays in C in ANSI, I'm confronted with an issue. Here's my code:
#include <stdio.h>
#include <string.h>
static int MAXLIGNE = 5000;
char *ptrlig[MAXLIGNE]; // PTR SUR LA LIGNE DE TXT // GOT AN ISSUE :
// VARIABLY MODIFIED PTRLIG # FILESCOPE
int lirelignes(char *ptrlig[], int nlignes);
void ecrirelignes(char *ptrlig[], int nlignes);
void trirapide(char *ptrlig[], int gauche, int droite);
Error from the GCC :
VARIABLY MODIFIED PTRLIG at FILESCOPE
I've seen that 'const' type may create that kind of issues. I tried to make it like :
#include <stdio.h>
#include <string.h>
static int MAXLIGNE = 5000;
unsigned char *ptrlig[MAXLIGNE];
But that doesn't seem to change anything in this case.

The length of an array defined at file scope must be a compile time constant, and the value of another variable does not qualify as such.
If you want to use a name for the length of this array, you'll need to use a macro:
#define MAXLIGNE 5000
char *ptrlig[MAXLIGNE];
The macro does a direct text substitution, so after the preprocessor stage it is the same as char *ptrlig[5000];

Related

How to share global array between c files

I am trying to share a global array between two files as below:
main.c:
#include <stdio.h>
#include "another.h"
int n=10;
int a[n];
void main(){
printf("Enter value:\n");
scanf("%d",&a[0]);
display();
}
another.h:
#include <stdio.h>
extern int n;
extern int a[n];
void display(){
printf("%d",a[0]);
return;
}
However, I am getting the following error:
variable modified 'a' at file scope
I'm not able to understand why I'm getting this error. Does anyone have an explanation?
The following appears to be an attempt at creating a variable length array. But regardless what it is actually, the 2nd of the following two lines is not legal:
extern int n;
extern int a[n];
n is not yet defined at the time it is used to create a.
In case you were thinking to create a VLA...
by definition VLAs are only created with automatic storage duration on the stack. This makes them unusable for use as extern or for any type of globally scoped variable.
However you can declare the size variable as an extern in a header file so that it is project global for any source file that includes that file, and once it is defined it can be used to size any array within project scope:
<some.h>
extern size_t array_size;
extern int gArray[100];
<some.c>
#include "some.h"
...
size_t array_size = 20;
int gArray[100] = {0};//Not a VLA
...
int main(void)
{
int array[array_size] = {0};
for(int i=0;i<sizeof(gArray);i++
{
//populate each element of gArray here
}
...
<someother.c>
#include "some.h"
int otherFunc(void)
{
//gArray is visible here just as it is in main(), with exactly the same values.
int local array[array_size] = {gArray[0],gArray[1],gArray[2],...,gArray[19]};
...

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

RAM browser with C programming language

I want to browse a part of the RAM. I tried with this code:
#include <stdio.h>
#include <string.h>
#define MIN ((volatile unsigned char*)0x00000000)
#define MAX ((volatile unsigned char*)0x0000ffff)
main()
{
volatile char* c;
for (c=MIN; c<MAX;c++) printf("c[%p]= %c\n",c,*c);
}
However the compiler display this message:
warning: comparison of distinct pointer types lacks a cast.
How I can resolve this problem?
c should have the same type as MIM/MAX: volatile unsigned char* c;.

C typedef in header file variably modified at file scope

I need to include some typedef definition in two source files:
typedef double mat[MATSIZE][MATSIZE] ;
so I created def.h which includes:
#ifndef DEF_H
#define DEF_H
typedef double mat[MATSIZE][MATSIZE] ;
#endif
and in both .c files I included it by:
in the first file processed:
#define MATSIZE 4
#include "def.h"
in the second .c file:
extern int MATSIZE;
#include "def.h"
But I get
error: variably modified ‘mat’ at file scope
What did I do wrong?
The concept of Variable Length Arrays (VLAs) is "new" to C99.
Before C99 you could only use real constants for specifying sizes of arrays. The following code was illegal either in block scope or file scope.
const int size = 42; /* size is not a real constant */
int boo[size];
C99 introduced VLA for block scope. The example code above is legal C99, provided it happens in block scope. Your definition is at file scope and therefore invalid.
Also it is a really bad bad idea to have the same typedef refer to two different types.
When arrays are defined outside a block (at file scope or global scope), the size must be known at compile time. That means that the each dimension on the array must be a constant integral value (or, for the first dimension, it could be implied by the initializer for the array).
If you used a C89 compiler, you might get a message about non-constant array dimensions. GCC 4.6.1 gives the 'variably modified mat at file scope' message.
C99 added Variable Length Arrays to the repertoire, but they can only appear inside a block or an argument list, where the size can be determined at runtime.
So, in a function, you could legitimately write:
extern int MATSIZE;
extern void func(void);
void func(void)
{
typedef double mat[MATSIZE][MATSIZE];
// ...
}
(The function declaration is needed to avoid the warnings like:
warning: no previous prototype for ‘func’ [-Wmissing-prototypes]
since I habitually compile with -Wmissing-prototypes.)
The other issue is that in one file, MATSIZE is a compile-time (#defined) constant; in the other, there is apparently an integer variable MATSIZE. These are completely unrelated. The types therefore are different.
typdef is block scoped
wildplasser is concerned about whether typedef is block-scoped or global. It is block-scoped, as this otherwise execrable code demonstrates:
#include <stdio.h>
static void function(void)
{
typedef int i;
i j = 1;
printf("j = %d\n", j);
{
typedef double i;
i j = 2.1;
printf("j = %f\n", j);
}
{
typedef char i[12];
i j = "this works";
printf("j = %s\n", j);
}
}
int main(void)
{
function();
return(0);
}
If that was present to me for code review, it would be summarily rejected. However, it amply demonstrates a point.
MATSIZE is not known. Which is why you are getting this issue.
#ifndef DEF_H
#define DEF_H
#define MATSIZE 100 /* or whatever */
typedef double mat[MATSIZE][MATSIZE]
#endif

Why does this code not compile?

Could anyone please explain why this code compiles :
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv [])
{
FILE *ptr;
char string[10] = "Testing";
ptr = fopen("C:\\Users\\Jordan\\Desktop\\Hello.txt", "wb");
fwrite(string,sizeof(string[0]), sizeof(string)/sizeof(string[0]), ptr);
}
Yet this does not : Gives an Error C2065:'string' : undeclared identifer
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv [])
{
FILE *ptr;
ptr = fopen("C:\\Users\\Jordan\\Desktop\\Hello.txt", "wb");
char string[10] = "Testing";
fwrite(string,sizeof(string[0]), sizeof(string)/sizeof(string[0]), ptr);
}
I am using Visual Studio 2010 on a Windows 7 Machine.
Thanks
Visual Studio uses the old C89/90 C. In that older C version, you can't mix declarations and code.
All your declarations must go on top. That's why the second example fails to compile.
// This a declaration
FILE *ptr;
// This is code
ptr = fopen("C:\\Users\\Jordan\\Desktop\\Hello.txt", "wb");
// This is another declaration. Not Allowed in C89/C90!!!
char string[10] = "Testing";
In (the C89 version of) C, all variables must be declared at the top of the block (the function, in this case). In your first example, you're doing that, in your second one you're not.
If you saved this file with a .c extension the compiler is interpreting it as a C source file, and since VC++ support for C is for C89, the C89 rules for variable declaration apply; in particular, in C89 you must declare all the local variables at the beginning of their block.

Resources