Question

-t-il viole les règles strictes d'aliasing pour déplacer des éléments de tout type autour de l'utilisation uint32_t, puis les relire? Si oui, est-il viole aussi des règles strictes d'aliasing à Memcpy d'un tableau de uint32_ts à un tableau de tout type, puis lire les éléments de retour?

L'exemple de code suivant illustre les deux cas:

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(void) {
    const char *strings[5] = {
        "zero", "one", "two", "three", "four"
    };
    uint32_t buffer[5];
    int i;

    assert(sizeof(const char*) == sizeof(uint32_t));

    memcpy(buffer, strings, sizeof(buffer));

    //twiddle with the buffer a bit
    buffer[0] = buffer[3];
    buffer[2] = buffer[4];
    buffer[3] = buffer[1];

    //Does this violate strict aliasing?
    const char **buffer_cc = (const char**)buffer;
    printf("Test 1:\n");
    for (i=0; i<5; i++)
        printf("\t%s ", buffer_cc[i]);
    printf("\n");

    //How about this?
    memcpy(strings, buffer, sizeof(strings));
    printf("Test 2:\n");
    for (i=0; i<5; i++)
        printf("\t%s ", strings[i]);
    printf("\n");

    return 0;
}

S'il vous plaît ne pas tenir compte de mon hypothèse d'une plate-forme 32 bits. En outre, si les éléments ne sont pas la même taille que uint32_t, je sais que les tapis et les copier est le nombre correct de uint32_t. Ma question porte sur l'opportunité de faire ou pas aliasing constitue une violation stricte.

Était-ce utile?

La solution

La première boucle Finalité techniquement aliasing strict violent - il accède à des objets uint32_t par un lvalue de type char *. Il est difficile de voir comment une Optimiseur te causerait un problème dans ce cas précis, cependant. Si vous avez modifié un peu pour que vous faisiez quelque chose comme:

printf("\t%s ", buffer_cc[0]);
buffer[0] = buffer[3];
printf("\t%s ", buffer_cc[0]);

peut voir la même chaîne imprimé deux fois -. Depuis l'optimisateur serait en droit de ne buffer_cc[0] de charge dans un registre une fois, parce que la deuxième ligne modifie seulement un objet de type uint32_t

La deuxième boucle, qui les memcpys arrière, est très bien.

Autres conseils

buffer_cc[0] et strings[3] (par exemple) sont des pointeurs qui font référence à la même emplacement mémoire mais sont du même type, ce qui ne viole pas aliasing stricte. buffer[0] est pas un pointeur, ne viole pas l'aliasing stricte. optimisations Aliasing surviennent lorsque déréférencement des pointeurs, donc je n'attendre à ce que causer des problèmes.

Comme vous faites allusion dans le code et le dernier paragraphe de votre question, le vrai problème dans l'exemple de code se pose lorsque des pointeurs et uint32_t sont de tailles différentes.

En outre, vous pouvez toujours un alias char* pour pointer vers un autre type sans violer aliasing strict, mais pas vice-versa.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top