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

pointeurs statiques constants dans une fonction

19 réponses
Avatar
Jean-Marie Delapierre
Bonjour,

Je voudrais écrire quelque chose dans le genre :

fonction (const int * const pointeur_source, int * const pointeur_resultat)

{

// Une variable dimensionnant les données dont la valeur est non connue
// au début de l'exécution de la fonction main(), mais connue à la
// première exécution de la présente fonction

extern const int int_taille_données;

// Variable temporaire statique pour des questions de performance
// Eviter de réaffecter la mémoire à chaque exécution

static int * const p_int_temp =
(int * const) malloc (int_taille_données * sizeof (int));

// Suite du code de la fonction

}

Problème :
Si j'ai bien compris, ce genre de code ne peut pas marcher dans la mesure
où les variables statiques sont affectées avant même le début de
l'exécution de la première instruction de la fonction main() écrite par
le programmeur.

Comment faire alors, sachant que pour des questions de sécurité du code,
je voudrais que le pointeur soit const (afin d'être sur qu'il ne puisse
être réaffecté par erreur sur une autre zone mémoire) et qu'il ne soit
visible que dans le corps de la fonction ?.

Cordialement.

Jean-Marie

Pour me répondre, remplacer "jm" par "jean-marie"

10 réponses

1 2
Avatar
Antoine Leca
Premier élément de réponse: en C, "const" est une indication pour le
compilateur, qui signifie à peu près "readonly". Ce n'est pas une protection
contre les erreurs.


En <news:,
Jean-Marie Delapierre va escriure:
Je voudrais écrire quelque chose dans le genre :

fonction (const int * const pointeur_source, int * const
pointeur_resultat)


Le premier const a un sens, mais les deux autres n'en ont pas (ne servent à
rien).


{

// Une variable dimensionnant les données dont la valeur est non
// connue au début de l'exécution de la fonction main(), mais
// connue à la première exécution de la présente fonction
extern const int int_taille_données;


const ne sert pas à cela. Tu dois te contenter de
extern int int_taille_données;
et refrener tes impulsions et ne pas assigner de nouvelle valeur à cette
variable, du moins dans cette fonction.

// Variable temporaire statique pour des questions de performance
// Eviter de réaffecter la mémoire à chaque exécution
static int * const p_int_temp > (int * const) malloc (int_taille_données * sizeof (int));


Exemple typique d'horreur aux quelles on arrive en C quand on torture le
langage (qui se laisse torturer de bonne grâce, il faut bien dire).

Tu fais deux choses bizarres ici :
-- d'abord, tu essayes d'écrire dans une constante une valeur variable (et
pour y arriver sans message d'erreur, tu utilises un transtypage)
-- ensuite, tu initialises à _chaque_ entrée dans la fonction (par un appel
à la fonction malloc()) un objet supposément invariable ; le compilateur
n'est pas content et te le fais savoir.


Si j'ai bien compris, ce genre de code ne peut pas marcher dans la
mesure où les variables statiques sont affectées avant même le début
de l'exécution de la première instruction de la fonction main()
écrite par le programmeur.


En gros, c'est cela.


Comment faire alors, sachant que pour des questions de sécurité du
code, je voudrais que le pointeur soit const (afin d'être sur qu'il
ne puisse être réaffecté par erreur sur une autre zone mémoire) et
qu'il ne soit visible que dans le corps de la fonction ?


Changer de langage. Le C n'est pas sûr.

(Bon, en fait ce n'est pas complètement vrai, il y a des moyens de faire ce
que tu veux. Le problème, c'est que si je te les explique, tu vas apprendre
comment changer la valeur d'un pointeur const, donc tu vas perdre ce qui
semble constituer ton objectif.
Et si tu prend ton parti du fait que const ne sert pas à cela, les
magouilles deviennent bruquement inutiles...)


Antoine

Avatar
Charlie Gordon
Antoine Leca wrote:

Premier élément de réponse: en C, "const" est une indication pour le
compilateur, qui signifie à peu près "readonly". Ce n'est pas une
protection contre les erreurs.
...

Changer de langage. Le C n'est pas sûr.

(Bon, en fait ce n'est pas complètement vrai, il y a des moyens de faire
ce que tu veux. Le problème, c'est que si je te les explique, tu vas
apprendre comment changer la valeur d'un pointeur const, donc tu vas
perdre ce qui semble constituer ton objectif.
Et si tu prend ton parti du fait que const ne sert pas à cela, les
magouilles deviennent bruquement inutiles...)


le compilateur peut mettre les variables globales declarees const dans un
segment de donnees non modifiable, les maguilles simples dont nous tairons
le detail peuvent causer des erreurs d'execution. A moins d'avoir recours
a des maguilles encore plus infames a base d'extern et d'incoherences entre
definition et declaration. Berk!

Chqrlie.

Avatar
Yves ROMAN
"Jean-Marie Delapierre" a écrit dans le message
de news:
Bonjour,

Je voudrais écrire quelque chose dans le genre :

fonction (const int * const pointeur_source, int * const
pointeur_resultat)

{

// Une variable dimensionnant les données dont la valeur est non connue
// au début de l'exécution de la fonction main(), mais connue à la
// première exécution de la présente fonction

extern const int int_taille_données;

// Variable temporaire statique pour des questions de performance
// Eviter de réaffecter la mémoire à chaque exécution

static int * const p_int_temp > (int * const) malloc (int_taille_données * sizeof (int));

// Suite du code de la fonction

}

Problème :
Si j'ai bien compris, ce genre de code ne peut pas marcher dans la mesure
où les variables statiques sont affectées avant même le début de
l'exécution de la première instruction de la fonction main() écrite par
le programmeur.

Comment faire alors, sachant que pour des questions de sécurité du code,
je voudrais que le pointeur soit const (afin d'être sur qu'il ne puisse
être réaffecté par erreur sur une autre zone mémoire) et qu'il ne soit
visible que dans le corps de la fonction ?.



Le mettre en const ne sera pas possible puisque tu modifies sa valeur.
Pour ne le faire qu'une fois, tu peux faire un truc du genre

fonction (int * pointeur_source, int * pointeur_resultat)
{
extern const int int_taille_données;
static int int_initialise = 0 ;
static int * p_int_temp = NULL ;

if ( ! int_initialise )
{
p_int_temp = malloc (int_taille_données * sizeof (int));
if ( p_int_temp == NULL )
{
// Traitement d'erreur
}
int_initialise = 1 ;
}
// Suite du code de la fonction
}

Avatar
Emmanuel Delahaye
Jean-Marie Delapierre wrote on 28/08/05 :
// Variable temporaire statique pour des questions de performance
// Eviter de réaffecter la mémoire à chaque exécution


Si elle static, elle n'est pas temporaire. Elle est parmanente (static
duration), mais, ici, sa portée est limitée au bloc dans lequel elle a
été définie.

static int * const p_int_temp > (int * const) malloc (int_taille_données * sizeof (int));


Marche pas. L'initialisation des données statiques se fait avant le
lancement du main(). On a pas le droit d'appeler des fonctions pour ça.

{
/* une fois a l'init */
static int * p_int_temp = NULL;

if (p_int_temp == NULL)
{
/* la premire fois ou a chaque fois que necessaire
* (p_int_temp == NULL)
*/
p_int_temp = malloc (taille_donnees * sizeof *p_int_temp);
}

if (p_int_temp != NULL)
{
/* toutes les fois que le pointeur est valide */
}
}

En principe, il faut un paramètre (ou une valeur spéciale du
paramètre), pour libérer le bloc et remettre le pointeur à NULL...

On peut s'en passer mais c'est un peu crade...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"

Avatar
Jean-Marie Delapierre
Le Mon, 29 Aug 2005 11:43:14 +0200, Yves ROMAN a écrit :

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern int *p_int_temp =
(int *) malloc (int_taille * sizeof (int));
}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)
{
extern const int int_taille_données;
extern int * const p_int_temp;

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c, au
bloc d'initialisation dans la fonction main() et à la fonction dans
laquelle le pointeur pointe de manière inamovible sur la zone mémoire de
travail.

Voila, ça marche, mais je me demande s'il n'y a pas moyen de faire plus
court et plus propre.

Cordialement.

Jean-Marie

Pour me répondre, remplacer "jm" par "jean-marie"

Avatar
Jean-Marie Delapierre
Le Mon, 29 Aug 2005 11:43:14 +0200, Yves ROMAN a écrit :

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern *p_int_temp;
p_int_temp = (int *) malloc (int_taille * sizeof (int));
}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)
{
extern const int int_taille_données;
extern int * const p_int_temp;

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c, au
bloc d'initialisation dans la fonction main() et à la fonction dans
laquelle le pointeur pointe de manière inamovible sur la zone mémoire de
travail.

Voila, ça marche, mais je me demande s'il n'y a pas moyen de faire plus
court et plus propre.

Cordialement.

Jean-Marie

Pour me répondre, remplacer "jm" par "jean-marie"

Avatar
Jean-Marie Delapierre
Le Mon, 29 Aug 2005 11:43:14 +0200, Yves ROMAN a écrit :

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern int *p_int_temp;
p_int_temp = (int *) malloc (int_taille * sizeof (int));
}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)
{
extern const int int_taille_données;
extern int * const p_int_temp;

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c, au
bloc d'initialisation dans la fonction main() et à la fonction dans
laquelle le pointeur pointe de manière inamovible sur la zone mémoire de
travail.

Voila, ça marche, mais je me demande s'il n'y a pas moyen de faire plus
court et plus propre.

Cordialement.

Jean-Marie

Pour me répondre, remplacer "jm" par "jean-marie"

Avatar
Jean-Marie Delapierre
Le Mon, 29 Aug 2005 11:43:14 +0200, Yves ROMAN a écrit :

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern int *p_int_temp;
p_int_temp = (int *) malloc (int_taille_donnees * sizeof (int));
}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)
{
extern const int int_taille_données;
extern int * const p_int_temp;

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c, au
bloc d'initialisation dans la fonction main() et à la fonction dans
laquelle le pointeur pointe de manière inamovible sur la zone mémoire de
travail.

Voila, ça marche, mais je me demande s'il n'y a pas moyen de faire plus
court et plus propre.

Cordialement.

Jean-Marie

Pour me répondre, remplacer "jm" par "jean-marie"

Avatar
Charlie Gordon
"Jean-Marie Delapierre" wrote in message
news:

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;


J'imagine que tu définis aussi int_taille_donnees (sans accent) comme ceci :
int int_taille_donnees;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern int *p_int_temp > (int *) malloc (int_taille * sizeof (int));


C'est très sale d'écrire cela en une seule ligne, essaie:

extern int *p_int_temp;
extern int int_taille_donnees;

int_taille_donnees = taille_qui_va_bien;
p_int_temp = malloc (int_taille_donnees * sizeof (*p_int_temp));

}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)


Les const sur les paramètres de la fonction sont pas très utiles et un peu
lourds.

{
extern const int int_taille_données;


sans accent, et par souci de cohérence tu devrais mettre le const plus près de
l'identificateur :
extern int const int_taille_donnees;

extern int * const p_int_temp;

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c,


C'est très confusant de l'appeler static.c, puisque justement ces données ne
sont pas static.
Pourquoi pas protected.c

au
bloc d'initialisation dans la fonction main() et à la fonction dans
laquelle le pointeur pointe de manière inamovible sur la zone mémoire de
travail.

Voila, ça marche, mais je me demande s'il n'y a pas moyen de faire plus
court et plus propre.


Ben oui, ca marche, mais ce n'est pas très fiable : si tu changes ultérieurement
le type de p_int_temp ou int_taille_donnees dans static.c et pas dans les autres
fichiers; le compilateur ne verra pas l'incohérence et le bug sera
potentiellement difficile à trouver.

Une alternative beaucoup moins sale (mais encore un peu dégueu) consiste à
déclarer ces variables globales dans un header commun de la facon suivante :

/* fichier ton_header.h */
#ifndef PROTECTED
#define PROTECTED const
#endif
extern int PROTECTED int_taille_donnees;
extern int * PROTECTED p_int_temp;

et à définir PROTECTED de la facon suivante en tête du fichier static.c avant
d'inclure ce header :

/* fichier main.c */

#define PROTECTED
#include "ton_header.h"
...
int PROTECTED int_taille_donnees;
int * PROTECTED p_int_temp;
...
int initialize_stuff() {
...
int_taille_donnees = taille_qui_va_bien;
p_int_temp = malloc(...);
...
}

int finalize_stuff() {
...
free(p_int_temp);
...
}

Tous les elements déclarés PROTECTED ne sont modifiables que dans le fichier qui
definit PROTECTED à rien.

On peut aussi s'interroger sur le choix des noms pour ces variables globales qui
n'ont rien de temporaire.

Enfin on peut peut-être appliquer cette technique à des champs de structure, ce
qui éviterait d'avoir recours à des variables globales.

On fait quand même la supposition que l'edition de liens ne sera pas perturbée
par cette incohérence en déclarations et définitions, je pense que cela
fonctionne sur beaucoup d'environnements, mais ce n'est pas garanti.

--
Chqrlie.


Avatar
Emmanuel Delahaye
Jean-Marie Delapierre wrote on 29/08/05 :
Le Mon, 29 Aug 2005 11:43:14 +0200, Yves ROMAN a écrit :

"Jean-Marie Delapierre" a écrit dans le message
de news:
[couic]


En fait, voila ce que j'ai fait pour obtenir le fonctionnement voulu :

un fichier static.c contenant juste :

int *p_int_temp;


Une globale ouverte à tous les vents ? Très mauvais...

Au minimum :

static int *p_int_temp;

Dans la fonction main(), le bloc suivant positionné après
l'initialisation de la variable int_taille et avant le premier appel à la
fonction :

{
extern int *p_int_temp
Argh, une globale publique. Non. Et si tu dois faire ça, fait le bien,

c'est à dire avec un header contenant la déclaration et inclus dans
static.c et dans les fichier qui l'utilisent... (et n'oublie pas la
garde contre les inclusions multiples).

http://mapage.noos.fr/emdel/notes.htm#globales

(int *) malloc (int_taille * sizeof (int));


Pourquoi ce satané cast. Ton compilateur est pré-ANSI ou quoi ?
malloc() retourne void*. Vire moi ces <f-word> casts...

http://mapage.noos.fr/emdel/notes.htm#malloc

}

Et enfin, le code de la fonction :

fonction (const int * const pointeur_source, int * const pointeur_resultat)
{
extern const int int_taille_données;


Meuh ? Tu as compilé ? En mode conforme, 'é' ne fait pas partie du
charset autorisé...

extern int * const p_int_temp;


Encore une fois, les declarations, ça ce met dans un header. Pas en
vrac comme çà, sans aucun contrôle de cohérence...

// Suite du code de la fonction

}

La portée du pointeur p_int_temp est limitée au fichier static.c, au


Sans le 'static', non. Et si tu mets le static, ceci

extern int * const p_int_temp;


n'a plus de sens (lien non résolu). Bref, tu fais en gros n'importe
quoi. Je ne comprends pas pourquoi tu écris des choses aussi
compliquées. Si tu veux un bon niveau d'abstraction (et en prime du
code gérant des données instanciables), étudie plutôt ceci :

http://mapage.noos.fr/emdel/tad.htm

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"


1 2