2010-09-21 3 views
6

J'ai une fonction qui prend un long * non signé et doit le passer à une bibliothèque externe qui prend un int * non signé et sur cette plate-forme unsigned int/long ont la même taille. Ceci génère un avertissement indiquant que ses règles de strict aliasing sont rompues. Y a-t-il du travail à faire?Une distribution qui brise les règles strictes d'aliasing

Merci

Edit: Je suis désolé de ne pas être clair. Le code est une mise à jour atomique, donc circuler dans la bibliothèque pour la stocker n'est pas une option. Je pourrais passer à l'assemblage, mais j'aimerais le faire en C++.

+0

juste pour un seul objet ou un tableau de longs/ints? – sellibitze

+0

C'est un magasin atomique pour un seul morceau de mémoire de 32 bits. – coderdave

Répondre

8
void UpdateVar(unsigned long* var) { 
    unsigned int x = static_cast<unsigned int>(*var); 
    ExternalLibUpdateVar(&x); 
    *var = static_cast<unsigned long>(x); 
} 
+0

Fais ce 'static_cast's, et je voterais. – sbi

+0

Désolé; n'a pas remarqué la balise C++ – dave

+0

Quelle est la vraie différence entre 'static_cast' et' reinterpret_cast' dans ce cas? – identity

2

Cela devrait fonctionner:

void UpdateVar(unsigned long* var) { 
    // this function will change the value at the address of var 
    ExternalLibUpdateVar(reinterpret_cast<unsigned int*>(var)); 
} 
+0

dangereux si sizeof (long)! = Sizeof (int) – nos

+0

Il a dit dans le message original qu'ils étaient garantis d'avoir la même taille sur sa plate-forme. Mais oui, vous avez raison. – identity

+1

+1. Dans certaines conditions, c'est effectivement approprié à mon avis. Mais cela dépend vraiment du cas et je me sentirais plus à l'aise avec une sorte de 'sizeof (int) == sizeof (long)' vérifier dans le programme qui fait échouer la compilation si la condition n'est pas remplie - C++ 0x 'static_cast' quelqu'un? :-) – sellibitze

0

Rien dans les mandats standard C qui int et long doivent avoir la même taille; de plus, même s'ils ont la même taille, rien dans la norme ne leur donne la même représentation (entre autres choses, ils pourraient avoir des combinaisons incompatibles de bits de remplissage et de représentation d'interruption, de sorte qu'un alias entre les deux types ne pourrait servir but utile).

Les auteurs de la norme ne voulaient pas forcer les plates-formes de ciblage où implémenteurs aliasing entre int et long ne servirait à rien de reconnaître ces aliasing. Ils ne voulaient pas non plus écrire des règles qui seraient applicables à certaines plateformes (celles où l'aliasing servirait un but) mais pas d'autres (celles où ce ne serait pas le cas). Au lieu de cela, ils ont pensé que les gens qui écrivaient des compilateurs de qualité essaieraient de reconnaître le crénelage dans les cas où cela serait utile. Etre capable d'utiliser des pointeurs sur un type 32 bits pour lire et écrire des valeurs d'un autre type 32 bits ayant la même représentation est clairement utile, en particulier si les API sont séparées en fonction du type attendu. Si certaines API courantes sur une plateforme utilisent int* pour les valeurs 32 bits et d'autres utilisent long*, une implémentation de qualité générale pour cette plate-forme doit permettre l'accès aux données de l'un ou l'autre type en utilisant les pointeurs de l'autre. Malheureusement, les auteurs de certains compilateurs sont plus intéressés par le traitement rapide d'un certain sous-ensemble de programmes que par le traitement d'un plus grand sous-ensemble de programmes, et ne peuvent pas compter sur un code utile s'il est nécessaire d'échanger des données. entre les API qui utilisent la même représentation de données mais différents types nommés à moins que l'une ne désactive complètement l'analyse d'alias. Bien sûr, si l'on vise des dialectes de C qui conviennent à une utilisation générale sur des microcontrôleurs, de tels problèmes n'ont pas d'importance.

Questions connexes