Newsgroup: it.comp.lang.c
Titolo: inizializzare una struccura statica costante

premetto che sto usando il compilatore IAR 78000 C-Compiler V3.21A/386 per i
microcontrollori nec da 8 bit.
voglio fare qualcosa del genere:
typedef struct rec
{
  const struct rec *succ;
  const struct rec *prec;
  char *str;
}Node_t;
static const Node_t n1;
static const Node_t n2;
static const Node_t n3;
static const Node_t n1 = { &n2, &n3, "Node 1" };
static const Node_t n2 = { &n3, &n1, "Node 2" };
static const Node_t n3 = { &n1, &n2, "Node 3" };
ma il compilatore da errore di "ridefinizione" sulle ultime 3 righe.
notare che ho provato la stessa cosa col gcc e funziona....
secondo voi come posso fare? ci sono alternative?
grazie
-- 
Mastupristi?


in questo modo le stai ridichiarando,
le ultime tre righe devono essere solo
n1 = ....
n2 = ....
...
Ciao,
Francesco



con che compilatorre le hai provate?
io ho provato sia con gcc che con lo iar e in entrambi i casi mi dice che
una riga
n1 = ...
e' interpretata come dichiarazione con tipo int, e questo fa conflitto con
la precedente dichiarazione.
quindi non va ancora.
ciao
-- 
Mastupristi?

 secondo voi come posso fare? ci sono alternative?
Certo: eliminare le tre righe indicate sopra.
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 A cosa servono le tre righe qui sopra!?
Ooops. Ho capito dopo a che servono.
Hai provato a mettere "extern" prima di "static"?


 Certo: eliminare le tre righe indicate sopra.
non le posso eliminare.
se guardi la definizione di n1 vedrai che fa riferimento a n2 e n3, che
vengono definite dopo. Se non metto le 3 righe che dici te il compilatore
dice che non conosce n2 e n3.
Ma se le metto mi dice che le ridefinisco....
esiste una soluzione? Mi sembra impossibile che non esista un modo per
inizializzare queste strutture! In pascal esisteva la dicghiarazione
forward....
ciao
ps: ho provato col gcc disabilitando le estensioni e funziona ancora.
-- 
Mastupristi?

 Hai provato a mettere "extern" prima di "static"?
"extern" e "static" fanno a cazzotti, semmai l'uno al posto dell'altro.


 Hai provato a mettere "extern" prima di "static"?
si e mi dice "Invalid storage class"
ciao
-- 
Mastupristi?

 "extern" e "static" fanno a cazzotti, semmai l'uno al posto dell'altro.
Oggi ho una certa tendenza a dir boiate...
--
Cingar


Mastupristi wrote:

static const Node_t *n1;
static const Node_t *n2;
static const Node_t *n3;
static const Node_t *n1 = { n2, n3, "Node 1" };
static const Node_t *n2 = { n3, n1, "Node 2" };
static const Node_t *n3 = { n1, n2, "Node 3" };
non l'ho provato, ma cosě dovrebbe funzionare

AlterX wrote:

le ultime tre righe senza static const Node_t :-[

 "extern" e "static" fanno a cazzotti, semmai l'uno al posto dell'altro.
se metto extern pero' cambio la storage class, io invece ho bisogno che
quelle costanti non escano dal modulo.
ciao
-- 
Mastupristi?


(cut)
č incredibile!!!!
non mi compila nulla, sto usando le static const ma a puntatore, e se 
provo ad allocare dinamicamente la memoria, mi da errore!
oltre a dirmi che ridichiaro la variabile!!

 Ma non devi poi gestirla la lista?
no
In realta' io creo una lista statica costante a tempo di compilazione che
rappresenta, per me, un menu' da fare apparire su un lcd.
Ho risorse piuttosto limitate, il nec 78F9026A che uso ha 16Kb di flash e
512 byte di ram.
Allo stato attuale ho occupati 506 byte di ram. Dato che il menu' non cambia
mai durante l'esecuzione dell'applicazione deve per forza finire in flash,
quindi mi serve che sia dichiarato const.
ciao
-- 
Mastupristi?

Mastupristi wrote:

Anche il Visual C++ da la ridifinazione

 le ultime tre righe senza static const Node_t :-[
ho provato con:
static const Node_t *n1;
static const Node_t *n2;
static const Node_t *n3;
 
*n1 = { n2, n3, "Node 1" };
*n2 = { n3, n1, "Node 2" };
*n3 = { n1, n2, "Node 3" };
e con
static const Node_t *n1;
static const Node_t *n2;
static const Node_t *n3;
 
n1 = { n2, n3, "Node 1" };
n2 = { n3, n1, "Node 2" };
n3 = { n1, n2, "Node 3" };
ma in entrambi i casi il compilatore dice
Warning[14]: Type specifier missing; assumed "int" 
Error[58]: Identifier 'n1' redefined      
e quindi con lo iar non va
ciao
-- 
Mastupristi?


1. Non puoi inizializzarli in quel modo.
2. Se li dichiari come puntatori devi allocare prima la memoria.
3. Essendo const, li dovresti inizializzare al momento della
dichiarazione, ma non potendolo fare, quando li vai a inizializzare
successivamente, il compilatore, anche gcc, ti da' un warning (gcc -Wall).
Io ho provato cosi':
static const Node_t n1, n2, n3;
int
main(void)
{
	n1.succ = &n2;
	n1.prev = &n3;
	n1.str	= "Nodo1";
	n2. .....ecc
	....
	n3.. .ecc
	......
	printf("%s %s", n1.str, n1.succ->str);
	return 0;
}
Questo funziona, anche se gcc da' warning sugli assegnamenti.
Le stesse operazioni fatte fuori dal main danno errore.


Su visual C++ non compila

 Su visual C++ non compila
Che errori da'?

 di euro abbia dei buchi come questo!
Il compilatore non ha nessun buco e fa bene a dirti che stai ridefinendo,
perché è esattamente quello che stai facendo.


Francesco Sgolacchia wrote:

sulle assegnazioni dice che l-value è const

 perché è esattamente quello che stai facendo.
Ma se non ci fosse il "const", la cosa sarebbe perfettamente lecita:
   int pippo; // Questa è solo una dichiarazione.
   int pippo; // Un'altra dichiarazione.
   extern int pippo; // Un'altra dichiarazione.
   int pippo = 3; // Questa è la vera definizione.
È strano che non si possa fare altrettanto con una variabile const.
--
Cingar


    int pippo = 3; // Questa č la vera definizione.
Non č cosě.


 Cingar
Fa bene il compilatore a dire che stai ridefinendo.
Pero` sono rimasto sorpreso quando ho scoperto che il gcc non da` 
nessun errore se tenti compilare le quattro righe sopra.  E` un 
comportamento che mi sembra strano, anche perche` se metti la stessa 
definizione di: 'int pippo;' in un altro file ti da` un errore in 
fase di link.
Ho perso ogni fiducia nel gcc!


 nessun errore se tenti compilare le quattro righe sopra. 
A me da' errore.



quoto :-)

 A me da' errore.
debian:~# cat test.c
#include <stdio.h>
typedef struct rec
{
  const struct rec *succ;
  const struct rec *prec;
  char *str;
}Node_t;
static const Node_t n1;
static const Node_t n2;
static const Node_t n3;
static const Node_t n1 = { &n2, &n3, "Node 1" };
static const Node_t n2 = { &n3, &n1, "Node 2" };
static const Node_t n3 = { &n1, &n2, "Node 3" };
int main()
{
        printf("Done.\n");
        return 0;
}
debian:~# gcc -pedantic -Wall test.c -o test
debian:~# ./test
Done.
debian:~# gcc -v
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)
debian:~#
Piu' di cosi' non so che fargli fare...
Ciaotutti,
*

 Piu' di cosi' non so che fargli fare...
La 2.95 e' una versione piuttosto vecchiotta di gcc.
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 grazie
Si PIC (altro tipo di uprocessori) esistono specifiche per il compilatore
per forzare l' allocazione di una costante o anche di una funzione in un
determinato indirizzo:
#ORG 0x1C00, 0x1C0F
CHAR CONST ID[10]= {"123456789"};
Se la tua è una necessità e non una curiosità, l' unica è specificare l'
indirizzo di allocazione delle 3 strutture; utilizzando la sintassi del 
CCS C compiler:
  typedef struct rec
  {
    struct rec *succ;
    struct rec *prec;
    char *str;
  }Node_t;
char str1[]="Nodo1";
char str2[]="Nodo2";
char str3[]="Nodo3";
#ORG 0x1000,0x1049
static const Node_t n1 = { 0x1050, 0x1100, str1 };
#ORG 0x1050,0x1099
static const Node_t n2 = { 0x1100, 0x1000, str2 };
#ORG 0x1100,0x1149
static const Node_t n3 = { 0x1000, 0x1050, str3 };
Ho tolto const all' interno della struttura (ha senso??) e ho dovuto
dichiarare e inizializzare le stringhe come vedi, tenete presente che CCS
C compiler è abb. una merda, magari con gcc si può inserire il testo
direttamente nella dichiarazione.
Spero di essere stato d' aiuto.
Z


Eh, ma la macchina in questione e' una debian woody :)
Ciaotutti,
*

 A me da' errore.
Che versioni usi? Io ho provato con GCC 3.3 e 3.4. Nessun errore.
 maxim@afton:~$ cat temp.c
 #include <stdio.h>
 typedef struct rec
 {
        const   struct  rec     *succ;
        const   struct  rec     *prec;
        char    *str;
 }Node_t;
 static const Node_t n1;
 static const Node_t n2;
 static const Node_t n3;
 static const Node_t n1 = { &n2, &n3, "Node 1" };
 static const Node_t n2 = { &n3, &n1, "Node 2" };
 static const Node_t n3 = { &n1, &n2, "Node 3" };
 int main()
 {
        printf("Done.\n");
        return  0;
 }
 maxim@afton:~$ gcc-3.3 -Wall temp.c
 maxim@afton:~$ ./a.out
 Done.
 maxim@afton:~$ gcc-3.4 -Wall temp.c
 maxim@afton:~$ ./a.out
 Done.
Max


Lo ritieni corretto?
Secondo me e` una assunzione che fa il gcc che se le strutture sono 
ridichiarate uguali sono la stessa cosa.  Difatti mi par di capire 
che le vecchie versioni l'errore lo davano.
E` questa un aggiornamento del C99?


 Non è così.
E' cosi. Questo è legale
int i;
int i=1;
int i;
int main(void)
{ return 0; }
 
Standard 1989 and Standard 1999
External object definitions
Semantics
   If the declaration of an identifier for an object has file scope
   and an initializer, the declaration is an external definition for
   the identifier.
   A declaration of an identifier for an object that has file scope
   without an initializer, and without a storage-class specifier or
   with the storage-class specifier static , constitutes a tentative
   definition  .If a translation unit contains one or more tentative
   definitions for an identifier, and the translation unit contains no
   external definition for that identifier, then the behavior is
   exactly as if the translation unit contains a file scope
   declaration of that identifier, with the composite type as of the
   end of the translation unit, with an initializer equal to 0.
   If the declaration of an identifier for an object is a tentative
   definition and has internal linkage, the declared type shall not be
   an incomplete type.
Examples
   int i1 = 1;                /*  definition, external linkage */
   static int i2 = 2;         /*  definition, internal linkage */
   extern int i3 = 3;         /*  definition, external linkage */
   int i4;                    /*  tentative definition, external
linkage */
   static int i5;             /*  tentative definition, internal
linkage */
   int i1;           /*  valid tentative definition, refers to
previous */
   int i2;           /*  $3.1.2.2 renders undefined, linkage
disagreement */
   int i3;           /*  valid tentative definition, refers to
previous */
   int i4;           /*  valid tentative definition, refers to
previous */
   int i5;           /*  $3.1.2.2 renders undefined, linkage
disagreement */
   extern int i1;    /*  refers to previous, whose linkage is external
*/
   extern int i2;    /*  refers to previous, whose linkage is internal
*/
   extern int i3;    /*  refers to previous, whose linkage is external
*/
   extern int i4;    /*  refers to previous, whose linkage is external
*/
   extern int i5;    /*  refers to previous, whose linkage is internal
*/
-- 
Horst

 
Conosco il C principalmente come sottoinsieme del C++. Quindi non ho
credenziali per pronunciarmi.
In C++ il codice in questione non è valido, ma non non posso esprimermi per
quanto riguarda il C, che potrebbe in questo aspetto discostarsi dal C++.
Quello che posso dire è che il codice viene compilato da tutte le versioni
del GCC che ho provato (2.91, 2.95, 3.3, 3.4). Non viene invece compilato,
se GCC è invocato con 'g++'.
Il Comeau online (
http://www.comeaucomputing.com/tryitout/
) si comporta nel
medesimo modo, ossia compila il codice in questione soltanto se viene
scelta la modalità C (C99 o C89). In modalità C++, il codice viene
rifiutato.
Naturalmente, non ci si può basare sul comportamento dei compilatori per
dedurre le regole del linguaggio, però il Comeau ha fama di essere molto
aderente allo Standard.
Max


Non credo, mi pare che il 2.95 non supporti le estensioni C99, e se vedi
sopra il mio post noterai che un 2.95 non da' errore...
Che poi non sia proprio corretto e' vero, secondo me la dichiarazione
corretta prevederebbe prima un extern - ma che senso ha dichiarare una
variabile extern e static allo stesso tempo?
Ciaotutti,
*

    int i1;           /*  valid tentative definition, refers to previous */
Ecco, a me questa con VCC causa un bel C2086. Quindi VCC non supporta lo
standard (sono shockato :P).
Ciaotutti,
*

 [...]
Ah, ecco, grazie. Cominciavo ad autoconvincermi di essermelo sognato.
--
Cingar

 int i = 0;
int i;
senza redefinizione sarebbe uguale a
int i=0;

Nel modo *C* ????
 
Ciao
Horst

 Nel modo *C* ????
Mmm, mo' mi hai fatto venire il dubbio... Ho usato il mio solito progettino
di test, quindi non ho fatto caso all'estensione, fammi un po' controllare.
OK, noto ora che il famoso progetto si chiama CPPTEST: la cosa avrebbe
dovuto mettermi una pulce nell'orecchio... :P
#include "stdio.h"
int i = 1;
int i;
int i;
int main(int argc, char* argv[])
{
    printf("i = %d", i);
}
Compiling...
test.c
Linking...
Creating browse info file...
CPPTEST.exe - 0 error(s), 0 warning(s)
Vaaaabene, okay. Funziona. Mea culpa :P
Ciaotutti,
*