J'ai essayé;
void *malloc(unsigned int);
struct deneme {
const int a = 15;
const int b = 16;
};
int main(int argc, const char *argv[])
{
struct deneme *mydeneme = malloc(sizeof(struct deneme));
return 0;
}
Et c'est l'erreur du compilateur:
gereksiz.c:3:17: error: expected ':', ',', ';', '}' or '__attribute__' before '=' token
Et aussi ceci;
void *malloc(unsigned int);
struct deneme {
const int a;
const int b;
};
int main(int argc, const char *argv[])
{
struct deneme *mydeneme = malloc(sizeof(struct deneme));
mydeneme->a = 15;
mydeneme->b = 20;
return 0;
}
Et c'est l'erreur du compilateur:
gereksiz.c:10:5: error: assignment of read-only member 'a'
gereksiz.c:11:5: error: assignment of read-only member 'b'
Et ni ont été compilés. Est-il possible d'initialiser une variable const dans une structure lors de l'allocation de mémoire avec malloc?
Vous devez rejeter le const pour initialiser les champs d'une structure mallocée:
struct deneme *mydeneme = malloc(sizeof(struct deneme));
*(int *)&mydeneme->a = 15;
*(int *)&mydeneme->b = 20;
Alternativement, vous pouvez créer une version initialisée de la structure et la mémoriser:
struct deneme deneme_init = { 15, 20 };
struct deneme *mydeneme = malloc(sizeof(struct deneme));
memcpy(mydeneme, &deneme_init, sizeof(struct deneme));
Vous pouvez rendre deneme_init statique et/ou global si vous le faites souvent (il ne doit donc être construit qu'une seule fois).
Explication de la raison pour laquelle ce code n'est pas un comportement indéfini, comme suggéré par certains commentaires, à l'aide des références standard C11:
Ce code ne viole pas 6.7.3/6 car l'espace renvoyé par malloc
n'est pas "un objet défini avec un type qualifié de const". L'expression mydeneme->a
n'est pas un objet, c'est une expression. Bien qu'il ait le type qualifié const
-, il désigne un objet qui n'a pas été défini avec un type qualifié const (en fait, il n'a pas été défini avec aucun type du tout).
La règle de repliement strict n'est jamais violée en écrivant dans l'espace alloué par malloc
, car le type effectif (6.5/6) est mis à jour à chaque écriture.
(La règle d'aliasing stricte peut être violée en lisant à partir de l'espace alloué par malloc
cependant).
Dans les exemples de code de Chris, le premier définit le type effectif des valeurs entières sur int
, et le second définit le type effectif sur const int
, mais dans les deux cas, la lecture de ces valeurs passe par *mydeneme
est correct car la règle de crénelage strict (6.5/7, puce 2) permet de lire un objet via une expression également ou plus qualifiée que le type effectif de l'objet. Puisque l'expression mydeneme->a
a le type const int
, elle peut être utilisée pour lire des objets de type effectif int
et const int
.
Avez-vous essayé de faire comme ça:
int main(int argc, const char *argv[])
{
struct deneme mydeneme = { 15, 20 };
struct deneme *pmydeneme = malloc(sizeof(struct deneme));
memcpy(pmydeneme, &mydeneme , sizeof(mydeneme));
return 0;
}
Je n'ai pas testé mais le code semble correct
Je ne suis pas d'accord avec la réponse de Christ Dodd , car je pense que sa solution donne Undefined Behavior conformément aux normes, comme d'autres l'ont dit.
Pour "contourner" le qualificatif const
d'une manière qui n'invoque pas un comportement indéfini, je propose la solution suivante:
void*
initialisée avec un appel malloc()
. struct deneme
et initialisez-le de manière à ce que le qualificateur const
ne se plaint pas (c'est-à-dire, dans la ligne de déclaration elle-même). memcpy()
pour copier les bits de l'objet struct deneme
dans l'objet void*
. struct deneme
et initialisez-le à la variable (void*)
, précédemment convertie en (struct deneme *)
. Donc, mon code serait:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct deneme {
const int a;
const int b;
};
struct deneme* deneme_init(struct deneme data) {
void *x = malloc(sizeof(struct deneme));
memcpy(x, &data, sizeof(struct deneme));
return (struct deneme*) x;
}
int main(void) {
struct deneme *obj = deneme_init((struct deneme) { 15, 20, } );
printf("obj->a: %d, obj->b: %d.\n", obj->a, obj->b);
return 0;
}
Intéressant, j'ai trouvé que cette méthode C99 fonctionnait en mode Clang mais pas en gcc
int main(int argc, const char *argv[])
{
struct deneme *pmydeneme = malloc(sizeof(struct deneme));
*pmydeneme = (struct deneme) {15, 20};
return 0;
}