Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Vocabulaire : variable locale

19 réponses
Avatar
candide
Bonjour,

Êtes-vous d'accord avec la définition suivante :

"Pour qu'une variable soit locale (ou automatique) il faut que sa portée soit
locale ainsi que sa persistance. "

?

La norme ne parle pas de variable locale/globale mais y-a-t-il un usage admis ?

10 réponses

1 2
Avatar
Antoine Leca
candide écrivit :
La norme ne parle pas de variable locale/globale mais y-a-t-il un usage admis ?



Quant tu parles de variables, te réfères-tu à l'objet (la case mémoire)
ou au nom (identificateur) qui sert à le désigner ?


Antoine
Avatar
candide
Antoine Leca a écrit :
candide écrivit :
La norme ne parle pas de variable locale/globale mais y-a-t-il un
usage admis ?



Quant tu parles de variables, te réfères-tu à l'objet (la case mémoire)
ou au nom (identificateur) qui sert à le désigner ?




Il me semble que dans la pratique quand on parle de variable on fait allusion à
l'identificateur, enfin , je ne parle pas de MON usage, mais de l'usage commun.
Avatar
Wykaaa
candide a écrit :
Bonjour,

Êtes-vous d'accord avec la définition suivante :

"Pour qu'une variable soit locale (ou automatique) il faut que sa portée soit
locale ainsi que sa persistance. "

?



Non, je ne suis pas du tout d'accord avec cette définition.
En effet, ça veut dire quoi "portée locale". Une variable auto est
visible dans les blocs fils du bloc où elle est déclarée sauf si une
variable de même nom y est déclarée. De plus, on ne parle de persistance
que pour les variables qui survivent à la mort de leur créateur (c'est à
dire à la fin de l'exécution du programme qui l'a écrite sur un support
EXTERNE.
On ne parle jamais de persistance pour une variable auto car elle est
allouée sur la pile d'exécution (en général, car il peut y avoir des
exceptions, sur certains compilateurs, pour des variables locales
volumineuses), alors la persistance...pfffiiitttt !

La norme ne parle pas de variable locale/globale mais y-a-t-il un usage admis ?



Et pour cause car c'est ambigu.

Il faut distinguer la classe d'allocation mémoire (auto, static, extern,
const, etc.) et la visibilité (le scope) car si je déclare, par exemple,
une variable "static" à l'intérieur d'une fonction, je ne pourrai
l'utiliser que dans cette fonction mais elle sera allouée avant la
première instruction exécutable du programme principal (main).
Avatar
candide
candide a écrit :


Il me semble que dans la pratique quand on parle de variable on fait allusion à
l'identificateur, enfin , je ne parle pas de MON usage, mais de l'usage commun.



D'ailleurs, cf. la note de bas de post de Richard Delorme ICI :

http://groups.google.fr/group/fr.comp.lang.c/msg/c73f687b3af1ae60?hl=fr
Avatar
candide
Wykaaa a écrit :

Et pour cause car c'est ambigu.



C'est vrai puisque ça peut référer à l'identificateur (portée) et un objet (durée)


Il faut distinguer la classe d'allocation mémoire (auto, static, extern,
const, etc.)



const n'est pas une classe de mémorisation. D'ailleurs, le terme de "classe" ne
réfèretait-il pas plutôt à la syntaxe du langage C et se distinguant ainsi de la
"durée de mémorisation" (je crois qu'ici certains disent "persistance", dans la
Norme "storage duration" je pense) ?

et la visibilité (le scope) car si je déclare, par exemple,
une variable "static" à l'intérieur d'une fonction, je ne pourrai
l'utiliser que dans cette fonction mais elle sera allouée avant la
première instruction exécutable du programme principal (main).



Mais si j'ai le code


while (1)
{
static int a[5];
int x;
extern int y;

/* code */
}

qu'est-il d'_usage_ (dans les "milieux autorisés" dont je ne fais pas partie) de
qualifier de variables locales ?
Avatar
Antoine Leca
candide écrivit :
Antoine Leca a écrit :
candide écrivit :
La norme ne parle pas de variable locale/globale mais y-a-t-il un
usage admis ?


Quant tu parles de variables, te réfères-tu à l'objet (la case mémoire)
ou au nom (identificateur) qui sert à le désigner ?



[...] quand on parle de variable on fait allusion à l'identificateur [...]



Alors pas d'accord, en C la portée est un attribut du nom mais la
«persistance» (selon mon interprétation, le concept également dénommé
durée de vie ou de stockage) est un attribut de l'objet.


Antoine
Avatar
Wykaaa
candide a écrit :
Wykaaa a écrit :

Et pour cause car c'est ambigu.



C'est vrai puisque ça peut référer à l'identificateur (portée) et un objet (durée)

Il faut distinguer la classe d'allocation mémoire (auto, static, extern,
const, etc.)



const n'est pas une classe de mémorisation.



Si, c'est une classe de mémorisation puisqu'un (bon) compilateur la
traiter différemment en l'allouant en mémoire non écrivible.
Typiquement, sur une machine à segments mémoire, les variables const
seront allouées dans un segment "unwritable".
D'ailleurs, le terme de "classe" ne
réfèretait-il pas plutôt à la syntaxe du langage C et se distinguant ainsi de la
"durée de mémorisation" (je crois qu'ici certains disent "persistance", dans la
Norme "storage duration" je pense) ?



Désolé mais "Storage duration" n'a rien à voir avec la persistance tel
que le terme est employé dans les langages de programmation.

Voici une Définition
La durée de vie d'un objet (au sens informatique du terme) peut dans
certains cas correspondre au besoin de celui-ci d'exister au delà du
temps d'exécution du programme qui l'a créé, l'adresse de l'objet "dans
l'espace" pouvant changer par rapport à son adresse de création. La
persistance est ainsi le fait "d'exister dans le temps". Un objet qui
reste en l'état quand il est sauvegardé puis chargé par une autre
application, ou à un moment éloigné, possède la propriété de
persistance. En conséquence, l'objet n'est plus dépendant de
l'application qui l'a créé.

Souvent les gens confondent la persistance de la valeur d'une variable
(d'un appel sur l'autre à une fonction, par exemple) avec la persistance
d'une variable, d'un objet, dans le temps.

et la visibilité (le scope) car si je déclare, par exemple,
une variable "static" à l'intérieur d'une fonction, je ne pourrai
l'utiliser que dans cette fonction mais elle sera allouée avant la
première instruction exécutable du programme principal (main).



Mais si j'ai le code


while (1)
{
static int a[5];
int x;
extern int y;

/* code */
}

qu'est-il d'_usage_ (dans les "milieux autorisés" dont je ne fais pas partie) de
qualifier de variables locales ?



En général, cela désignera la variable auto x car elle est allouée dans
la pile d'exécution sur le prologue d'entrée dans le bloc généré par le
compilateur et elle est désallouée quand on sort du bloc (même si ce
n'est pas par l'accolade fermante que l'on sort).

le tableau a et l'extern y seront, de toute façon, alloués par l'éditeur
de liens et non par le compilateur.
y ne peut pas être locale puisque des déclaration "extern int y" peuvent
se trouver ailleurs dans l'application. Ses déclaration feront toutes
référence à la même définition de y.
Avatar
Mickaël Wolff
Wykaaa a écrit :
const n'est pas une classe de mémorisation.



Si, c'est une classe de mémorisation puisqu'un (bon) compilateur la
traiter différemment en l'allouant en mémoire non écrivible.
Typiquement, sur une machine à segments mémoire, les variables const
seront allouées dans un segment "unwritable".



Je pense que tu généralises trop. De toute façon, je pense aussi
qu'on est parti du mauvais pied sur cette discussion. Vous parlez tous
sans jamais préciser le contexte de déclaration des variables, alors que
c'est certainement ce qu'il y a de plus important.

Qu'une variable globale, c'est à dire une variable déclarée au niveau
d'une unité de compilation, déclarée const soit placée par le
compilateur dans un segment protégé en écriture, je suis d'accord. Et
c'est ce que je m'attends à ce que le compilateur fasse. Même si je m'en
fou, et que l'important est que la constance de la variable soit
contrôlée à la compilation. Mais pour une variable locale normale (pas
déclarée static), c'est à dire déclarée dans un flux d'exécution, je ne
vois pas pourquoi le compilateur s'embêterait à allouer de la mémoire
dans un segment constant. Pour la simple et bonne raison que les
variables locales sont allouées sur la pile et non sur le tas.

À moins que je n'ai pas compris une subtilité.

Cependant, que le compilateur utilise des segments invariables pour
des variables constantes me parait bizarre. Cela signifierait qu'il est
illégal de transtyper une variable constante en son pendant variable, et
de l'utiliser en tant que tel. On constatera aussi que le C++,
particulièrement influencé par le C, propose un opérateur de transtypage
dédié à ce genre d'opérations const_cast<>, ce qui va dans le sens de ma
compréhension de l'usage des variables constantes : la constance d'une
variable est une protection supplémentaire pour aider le programmeur
dans son travail, et non une barrière absolue.

Enfin bref, un exemple pour aider à clore le débat me semble
nécessaire. N'étant pas un programmeur très expérimenté, il e peut que
le code suivant agrémenté de commentaires soit imprécis, et manque
d'exhaustivité. J'invite les participant à me corriger (gentillement) et
à compléter :



== scope.c =
/* En considérant les abréviations :
* - Segment de Données Statiques SDS
* - Segment de Données Globales SDG
*
* Les variables globales et statiques on un espace mémoire réservé
* alloué (et initialisé à 0) au chargement de l'exécutable
*
* Les variables locales sont allouée lors de l'entrée dans le bloc
* d'exécution dans lequel elles sont déclarées, et ne sont pas
* initialisées.
*/
int g ; /* portée globale au programme, alloué dans le SDG */
static int gs ; /* portée globale à l'unité de compilation,
* alloué dans le SDG (ou SDS ?)
*/

int /* portée inexistante, allouée sur la pile */
main
( int argc /* portée locale à la fonction, allouée sur la pile */
, char ** argv
)
{
int l ; /* portée locale à la fonction, allouée
* sur la pile
*/
static ls ; /* portée locale à la fonction, allouée
* dans le SDS
*/

{
int lb ; /* portée locale au bloc, allouée sur la
* pile
*/
}

return 0 ;
}

============
Par contre, qu'est-ce que vous entendez par variable auto ? Le seul
endroit où j'ai entendu parlé d'un tel modificateur c'est en C++. Et ça
n'a rien à voir avec la portée ^^;

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
Avatar
espie
In article <49889d6d$0$18851$,
Mickaël Wolff wrote:
Cependant, que le compilateur utilise des segments invariables pour
des variables constantes me parait bizarre. Cela signifierait qu'il est
illégal de transtyper une variable constante en son pendant variable, et
de l'utiliser en tant que tel. On constatera aussi que le C++,
particulièrement influencé par le C, propose un opérateur de transtypage
dédié à ce genre d'opérations const_cast<>, ce qui va dans le sens de ma
compréhension de l'usage des variables constantes : la constance d'une
variable est une protection supplémentaire pour aider le programmeur
dans son travail, et non une barrière absolue.



Non, non, il a le droit. La plupart des manipulations visant a faire sauter
un const sont du domaine de l'undefined behavior.

Par contre, la nature du const est variable, si c'est un const "de typage",
en general, on s'en fout, si c'est un const "de definition de l'objet", la
ca peut tres bien etre protege contre l'ecriture intempestive du
Mickaël Wolff qui passait par la...

L'exemple le plus celebre etant certainement les chaines de caracteres
constantes, qui sont sur pas mal de compilateurs explicitement placees dans
la zone de code (donc en lecture seule) quand c'est possible depuis quelques
annees, il y a meme un flag sur gcc pour desactiver ce comportement
(-fwritable-strings), precisement pour faire tourner du code anterieur (et non
conforme a la norme).
Avatar
Wykaaa
Mickaël Wolff a écrit :
Wykaaa a écrit :
const n'est pas une classe de mémorisation.



Si, c'est une classe de mémorisation puisqu'un (bon) compilateur la
traiter différemment en l'allouant en mémoire non écrivible.
Typiquement, sur une machine à segments mémoire, les variables const
seront allouées dans un segment "unwritable".



Je pense que tu généralises trop. De toute façon, je pense aussi qu'on
est parti du mauvais pied sur cette discussion. Vous parlez tous sans
jamais préciser le contexte de déclaration des variables, alors que
c'est certainement ce qu'il y a de plus important.

Qu'une variable globale, c'est à dire une variable déclarée au niveau
d'une unité de compilation, déclarée const soit placée par le
compilateur dans un segment protégé en écriture, je suis d'accord. Et
c'est ce que je m'attends à ce que le compilateur fasse. Même si je m'en
fou, et que l'important est que la constance de la variable soit
contrôlée à la compilation. Mais pour une variable locale normale (pas
déclarée static), c'est à dire déclarée dans un flux d'exécution, je ne
vois pas pourquoi le compilateur s'embêterait à allouer de la mémoire
dans un segment constant. Pour la simple et bonne raison que les
variables locales sont allouées sur la pile et non sur le tas.



Comme l'a dit Marc Espie, les constantes locales chaînes de caractères
peuvent être allouées dans le code (donc en lecture seule). Sur une
machine à segment mémoire, elle seront allouées en tête d'un segment de
code marqué, donc, non écrivible.

À moins que je n'ai pas compris une subtilité.

Cependant, que le compilateur utilise des segments invariables pour
des variables constantes me parait bizarre. Cela signifierait qu'il est
illégal de transtyper une variable constante en son pendant variable, et
de l'utiliser en tant que tel. On constatera aussi que le C++,
particulièrement influencé par le C, propose un opérateur de transtypage
dédié à ce genre d'opérations const_cast<>, ce qui va dans le sens de ma
compréhension de l'usage des variables constantes : la constance d'une
variable est une protection supplémentaire pour aider le programmeur
dans son travail, et non une barrière absolue.



Il y a des constantes que je ne doit absolument pas modifier, par
quelque moyen que ce soit, dans certaines applications (en particulier
dans un système d'exploitation).

Enfin bref, un exemple pour aider à clore le débat me semble
nécessaire. N'étant pas un programmeur très expérimenté, il e peut que
le code suivant agrémenté de commentaires soit imprécis, et manque
d'exhaustivité. J'invite les participant à me corriger (gentillement) et
à compléter :



== scope.c = >
/* En considérant les abréviations :
* - Segment de Données Statiques SDS
* - Segment de Données Globales SDG
*
* Les variables globales et statiques on un espace mémoire réservé
* alloué (et initialisé à 0) au chargement de l'exécutable
*
* Les variables locales sont allouée lors de l'entrée dans le bloc
* d'exécution dans lequel elles sont déclarées, et ne sont pas
* initialisées.
*/
int g ; /* portée globale au programme, alloué dans le SDG */
static int gs ; /* portée globale à l'unité de compilation,
* alloué dans le SDG (ou SDS ?)
*/

int /* portée inexistante, allouée sur la pile */
main
( int argc /* portée locale à la fonction, allouée sur la pile */
, char ** argv
)
{
int l ; /* portée locale à la fonction, allouée
* sur la pile
*/
static ls ; /* portée locale à la fonction, allouée
* dans le SDS
*/

{
int lb ; /* portée locale au bloc, allouée sur la
* pile
*/
}

return 0 ;
}

============ >
Par contre, qu'est-ce que vous entendez par variable auto ? Le seul
endroit où j'ai entendu parlé d'un tel modificateur c'est en C++. Et ça
n'a rien à voir avec la portée ^^;



Les paramètres de main (argc et argv) ne sont pas considérés comme des
variables locales (ils ne sont pas forcément alloués sur la pile).
Souvent, ce qui est alloué sur la pile, pour les paramètres des
fonctions, c'est un pointeur vers l'endroit où ils ont été alloués.
Ca dépend des machines, des environnements, etc.
Sur des systèmes d'exploitation où le format d'unité de compilation est
standardisé entre les différents compilateurs (pour faciliter la
communication inter-langages), les paramètres formels ne sont pas
alloués dans la pile d'exécution.

Variables auto :
"auto" est un mot clé en C mais il est rarement utilisé car, par défaut,
les variables locales, sont de classe mémoire auto.

{
int i; /* equivalent à : auto int i; */
}
1 2