array modificat variabil în domeniul de aplicare al fișierului în C (Programare, C, Array-Uri, Static)

utilizator707549 a intrebat.

Am un cod de genul acesta:

static int a = 6;
static int b = 3;

static int Hello[a][b] =
{
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3}
};

dar când îl compilez, îmi spune eroare:

‘Hello’ modificat variabil în cadrul fișierului

cum se poate întâmpla asta și cum aș putea să o rezolv?

Comentarii

  • Posibil duplicat al array-ului modificat în mod variabil la nivelul fișierului –  > Por tstew.
4 răspunsuri
zch

Nu puteți avea matrice statică a cărei dimensiune este dată ca o variabilă

De aceea, constantele ar trebui să fie #defined:

#define a 6

În acest fel preprocesorul va înlocui a cu 6, , ceea ce face ca declarația să fie validă.

Comentarii

  • este a și b definite ca int a = 6; int b = 3 în loc de static int a = 6 funcționează? – user707549
  • Nu, aceasta va fi în continuare o variabilă. Utilizați #define. În C++ există const care ar permite const int a = 6; să funcționeze, dar chiar și const nu este suficient în C. –  > Por zch.
  • o alternativă la macro este utilizarea enumerațiilor anonime, care sunt adevărate constante de numere întregi. enum { a = 6, b = 3, }; –  > Por tstanisl.
Omkant

Răspuns simplu variable modified array at file scope is not possible.

Detaliat :

faceți-o la compilare integral constant expression, , deoarece lungimea matricei trebuie specificată în momentul compilării.

astfel :

#define a 6
#define b 3

Sau, urmați standardul c99. și compilați ca pentru gcc.

gcc -Wall -std=c99 test.c -o test.out

Problema aici este că array-ul de lungime variabilă cu lungimea furnizată poate să nu fie inițializat, astfel încât primiți această eroare.

pur și simplu

static int a =6;
static int b =3;

void any_func()
{
int Hello [a][b]; // no need of initialization no static array means no file scope.
}

Acum folosiți for loop sau orice buclă pentru a umple matricea.

Pentru mai multe informații, doar un DEMO :

#include <stdio.h>
static int a = 6; 
int main()
{
int Hello[a]={1,2,3,4,5,6}; // see here initialization of array Hello it's in function
                            //scope but still error
return 0;
}


[email protected]:~/c# clang -std=c99 vararr.c -o vararr
vararr.c:8:11: error: variable-sized object may not be initialized
int Hello[a]={1,2,3,4,5,6};
          ^
1 error generated. 

Dacă eliminați static și furnizați inițializarea, atunci se va genera o eroare ca mai sus.

Dar dacă păstrați atât static cât și inițializarea, tot va apărea o eroare.

Dar dacă eliminați inițializarea și păstrați static va apărea eroarea de mai jos.

error: variable length array declaration not allowed at file scope
static int Hello[a];
           ^     ~
1 error generated.

Așadar, declararea matricei de lungime variabilă nu este permisă în domeniul de aplicare al fișierului, deci faceți-o în domeniul de aplicare al funcției sau al blocului în interiorul oricărei funcții (dar nu uitați că dacă o faceți în domeniul de aplicare al funcției trebuie să eliminați inițializarea).

NOTĂ : Deoarece este C etichetat, deci dacă se face a și b ca const nu vă va ajuta, dar în C++ const va funcționa bine.

Comentarii

  • C99 nu suportă nici VLA-urile la nivel de fișier. Trebuie să fie la nivel de funcție sau mai mic. El „poate” folosi const declarațiile de indexare, inclusiv static const int a = 10; de exemplu, la nivelul fișierului. –  > Por WhozCraig.
  • Este o chestie de stivă. Dacă sunt acceptate de compilatorul C99, nu este obligatoriu să fie așa; standardul definește modul în care se comportă dacă C99 face le acceptă. Implementările folosesc stack-math pentru a le implementa. Nu puteți face acest lucru la nivel de compilare globală (sau de fișier) a segmentelor de date. –  > Por WhozCraig.
  • @WhozCraig: Dar atunci când definesc a în main în acest caz, de asemenea, nu funcționează, compilarea cu -std=c99 . acum a este pe stivă, deci care este problema acum, am încercat cu gcc și clang –  > Por Omkant.
  • @WhozCraig: Am citit undeva pe SO însuși, așa că am postat răspunsul, dar acum mă confrunt și eu cu această problemă cu -std=c99 și nu se compilează, vreun indiciu? am de gând să editez și eu răspunsul meu – -.  > Por Omkant.
  • @WhozCraig : Am înțeles, te înșeli în legătură cu chestia cu stiva, ar putea fi globală.  > Por Omkant.
PolarBear2015

Atunci când se utilizează CLANG/LLVM, funcționează următoarele:

static const int a = 6;
static const int b = 3;

static int Hello[a][b] =
{
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3}
}; 

(Pentru a-l vedea în ansamblul generat, trebuie să se utilizeze Hello, astfel încât să nu fie optimizat)

Cu toate acestea, acest lucru va genera o eroare dacă este selectat modul C99 (-std=c99), va genera doar un avertisment (Wgnu-folding-constant) dacă este selectat -pedantic.

GCC nu pare să permită acest lucru (const este interpretat ca fiind doar de citire)

Vedeți explicația în acest fir de discuție:

Eroare „Initializer element is not constant” fără motiv în GCC Linux, compilarea C

Comentarii

  • Cuvântul cheie „const” în C nu înseamnă cu adevărat „constant”. Acest lucru îi induce în eroare pe unii utilizatori. –  > Por Putere redusă.
  • @Lowpower Sunt de acord – acesta este un detaliu al implementării. În plus, implementarea efectivă a costului pare să varieze, în C++ cel puțin unele const nu mai sunt „read only variable” (ceea ce înseamnă că nu există niciun simbol în tabela de simboluri care să indice segmentul de memorie read-only), ci adevărate constante rezolvate la compilare. –  > Por PolarBear2015.
Scott Franco

Da, acest lucru este enervant:

const int len = 10;

int stuff[len];

Dă eroarea. Încerc să mă îndepărtez de a face #define x, deoarece const int este o modalitate mai bună de a declara o constantă, dar apoi aveți aceste cazuri în care const int nu este o constantă adevărată, chiar dacă compilatorul știe foarte bine că este.