Question

Que puis-je faire pour éviter cette erreur MISRA donnant le code ci-dessous? J'ai essayé avec la coulée (unit16_t). Mais il n'a pas permis à une conversion explicite.

conversion implicite illégale de sous-jacent de type MISRA "unsigned char" à l'expression complexe "unsigned int" (Misra C 2004 règle 10.1)

 uint8_t rate = 3U; 
 uint8_t percentage = 130U;      
 uint16_t basic_units = rate * percentage;
Était-ce utile?

La solution

Le problème est que sont promus en silence à la fois le taux et le pourcentage des promotions entières de type « int ». La multiplication est donc réalisée sur un type signé.

MISRA code compatible consiste à réécrire soit le code tel

 uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

ou faire comme le suggère MISRA, immédiatement typecast le résultat d'une expression à son "type sous-jacent":

 uint16_t basic_units = (uint8_t)(rate * percentage);

EDIT: Clarification suit

.

ISO 9899: 1999 6.3.1.1 2

Si un int peut représenter toutes les valeurs du type d'origine, la valeur est convertie en un int; sinon, il est converti en un entier non signé. Ceux-ci sont appelés entier promotions .

Texte informatif de MISRA-C:

MISRA-C: 2004 6.10.3 conversions de types dangereux:

/ - /

- Changement de signedness dans les opérations arithmétiques: promotion intégrale se traduira souvent en deux opérandes non signés donnant un résultat de type (signé) int . Par exemple, l'ajout de deux 16 bits opérandes non signés donnera un résultat de 32 bits signé si int est de 32 bits, mais un résultat de 16 bits non signé si int est 16 les bits.

Je ne suis pas vraiment sûr que la 2ème ligne de la mine serait au-dessus de satisfaire MISRA ou non, à la deuxième cru que je peux avoir confondu MISRA 10,1 avec 10,5, lorsque ce dernier applique une de la distribution immédiate de type sous-jacent, mais seulement en cas de certains opérateurs binaires.

J'ai testé deux lignes avec l'analyse de code statique LDRA et il ne se plaignait pas (mais donne quelques avertissements incorrectes, non liées), mais aussi LDRA fonctionne très mal à MISRA-C.

Quoi qu'il en soit, le problème dans la question initiale est que le taux et le pourcentage sont tous deux convertis implicitement par les promotions entières type int qui est signé, depuis int peut représenter tous valeurs d'une uint8_t. Ainsi, il devient

uint16_t basic units = (int)rate * (int)percentage.

Pour éviter cela, vous devez explicitement cataloguée. Après avoir donné plus pensé, je partirais avec la 1ère ligne de mes deux ci-dessus.

Autres conseils

La conversion implicite est effectuée avant la multiplication, pour la multiplication. Peut-être une conversion explicite juste avant la multiplication se ferme jusqu'à votre outil

uint16_t basic_units = (unsigned)rate * (unsigned)percentage;

La valeur unsigned résultante, doit être converti implicitement uint16_t sans avertissement. Si votre outil choisit d'être un PITA à ce sujet aussi, essayez une autre conversion explicite:

uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage);

La règle de MISRA essaie de faire en sorte que le « type sous-jacent » utilisé pour le calcul est le même que le type résultant. Pour ce faire, vous pouvez lancer une, ou les deux, des opérandes:

uint8_t rate = 3U; 
uint8_t percentage = 130U;      
uint16_t basic_units = (uint16_t)rate * percentage;

Cependant, sur une architecture 32 bits le résultat sans le casting est OK, considérer les points suivants:

uint32_t rate =  ...;
uint32_t percentage = ...;
uint64_t basic_units = rate * percentage;

Sur une architecture 32 bits, l'opération sera réalisée en 32 bits - même si le type de cible est de 64 bits. Où le taux et le pourcentage sont assez grandes, cela pourrait entraîner l'emballage de fonctionnement en 32 bits et donc des données qui auraient ajustement dans le type de cible sera perdue.

La règle MISRA tente de rendre le code plus sûr, quelle que soit la taille des types sur la plate-forme cible.

Si vous essayez de caster vos opérandes en utilisant la coulée de type C, vous pourriez donner à votre outil autre chose à se plaindre. Ainsi, au lieu de faire ceci:

uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

Vous pouvez avoir besoin de faire ceci:

uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top