2 votes

S'agit-il d'une violation stricte de l'aliasing ?

struct __packed element {
    char val;
};

void foo(struct element arr[4], uint32_t a) {
    uint32_t* i = (uint32_t*)arr;
    *i = a;
}

int main(void) {
    struct element arr[4] __aligned(4);

    foo(arr, 5);
    ...
}

Comme le titre l'indique, s'agit-il d'une violation stricte de l'aliasing en C ?

En supposant que le type stocké de arr est struct element[4]

5voto

user694733 Points 4040

Oui, cette ( *i = a ) est une violation stricte de l'aliasing.

N1570 §6.5 p7 :

L'accès à la valeur stockée d'un objet ne peut se faire qu'au moyen d'une expression lvalue ayant l'un des types suivants l'un des types suivants : 88)

  • un type compatible avec le type effectif de l'objet,
  • une version qualifiée d'un type compatible avec le type effectif de l'objet,
  • un type qui est le type signé ou non signé correspondant au type effectif de l'objet. l'objet,
  • un type qui est le type signé ou non signé correspondant à une version qualifiée du type effectif de l'objet. type effectif de l'objet,
  • un type d'agrégat ou d'union qui comprend un des types susmentionnés parmi ses membres (y compris, récursivement, un membre d'un sous-agrégat ou d'une union contenue), ou
  • un type de caractère.

Aucune des conditions ci-dessus n'est remplie :

  • uint32_t n'est pas compatible avec le type effectif char .

  • Aucun type qualifié de char utilisé.

  • uint32_t n'est pas la version non signée de char .

  • struct element n'a pas uint32_t membres.

  • uint32_t n'est pas un type de caractère.

Il serait légal que le type effectif du tableau original soit uint32_t ou il serait alloué avec malloc pour lequel le type effectif a lieu lors de l'affectation.

uint32_t arr;
foo((struct element*)&arr, 5); // Possible pointer conversion issues still apply

o

void * arr = malloc(4);
foo(arr, 5);

Notez que uint32_t* i = (uint32_t*)arr pourrait également conduire à comportement indéfini si l'adresse convertie ne peut pas être enregistrée dans uint32_t* type variable. Mais c'est spécifique à la mise en œuvre et dépend donc de votre plate-forme.

3voto

alain Points 1226

Cela dépend de la façon dont vous allez lire element arr[4] et sur la façon dont arr a été attribué.

Si vous le lisez comme

uint32_t value = *(uint32_t*)arr;

y arr a été alloué dynamiquement (en utilisant malloc ), ou alloué comme un int32_t objet avec une durée de stockage automatique ("on the stack"), c'est OK.
Si c'est le cas, votre écriture change le type effectif en int32_t .
Mais si vous voulez lire en utilisant un type non lié à uint32_t et non un type de caractère, c'est un comportement non défini.

Aussi, arr doit être correctement aligné pour int32_t . (Si elle a été obtenue en utilisant malloc il l'est automatiquement).


Après que la question ait été modifiée, il est devenu clair qu'il s'agit en effet d'un comportement non défini, car arr est réparti comme suit :

struct element arr[4] __aligned(4);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X