2016-02-08 4 views
2

J'ai une API qui implémente une opération d'écriture dans EEPROM. Voici sa déclaration:Conversion entre uint8 et char en C

CYBLE_API_RESULT_T CyBle_StoreAppData (uint8 * srcBuff, const uint8 destAddr[], uint32 buffLen, uint8 isForceWrite); 

Il fonctionne bien quand je l'appelle cette fonction et envoyer un paramètre de tableau à srcBuff qui a été déclarée en tant que type uint8.

Le problème est, j'ai besoin d'envoyer le pointeur de tableau char. Je pensais que char est déjà un uint8, mais j'obtiens un avertissement de compilateur si j'envoie un pointeur de tableau char à cette fonction au lieu de uint8. Pourquoi ne puis-je pas utiliser char au lieu de uint8? Voici 2 exemples d'appel: cette fonction

static const uint8  datastack_ROM[dedicatedRomSize] = {0}; 
uint8     Container_ID[10]; 
char     Prefix[10]; 

//Call the function with Container_ID which has been declared as uint8. This is working. 
CyBle_StoreAppData(Container_ID,datastack_ROM,10,0); 

//Call the function with Prefix which has been declared as char. This is NOT working. 
CyBle_StoreAppData(Prefix,datastack_ROM,10,0); 

Voici l'avertissement pour le second appel:

passing char[10] to parameter of type 'uint8 *' converts between pointers to integer types with different sign.

Ne sont pas char et uint8 même?

+1

La chose importante dans le message d'erreur est la partie sur "signe différent". Cela signifie que votre type 'char' est' signed' alors que 'uint8' est (supposé ici)' unsigned'. Cela ne va probablement pas être un gros problème, vous devriez juste pouvoir lancer votre pointeur: 'CyBle_StoreAppData ((uint8 *) Prefix, ...)' –

+0

Cela semble être une violation de contrainte, attention: http: // stackoverflow.com/questions/30535814/passe-unsigned-char-pointeur-à-atoi-sans-cast –

+0

@GiorgiMoniava J'ai regardé les questions similaires mais je suppose que je ne pouvais pas trouver ça. Comment puis-je mentionner qu'il y a une question similaire à cela? Ou suis-je celui qui a besoin de faire ça? –

Répondre

1

Les deux types ont une longueur de 8 bits. La différence vient avec la signature.

  • Le type uint8 n'est pas signé. Le type char doit être signé dans votre cas. En fait, il dépend du compilateur, mais la plupart des compilateurs considèrent le type char comme étant signé par défaut et ont une option pour forcer le type char comme non signé si nécessaire. Voir la C99 standard document reference §6.2.5p15:

La mise en œuvre définit l'omble d'avoir la même gamme, la représentation et le comportement que soit signé char ou unsigned char.

CHAR_MIN, défini dans limits.h, aura l'une des valeurs 0 ou SCHAR_MIN, et cela peut être utilisé pour distinguer les deux options.

+0

Je ne pensais pas que cela dépendait du compilateur. J'ai trouvé ce lien [link] (https://developer.mbed.org/handbook/C-Data-Types). Mais si je déclare le 'Container_ID' comme non signé, je ne peux pas utiliser la fonction de chaîne que je les utilise pour un autre travail. Donc je devrais le lancer comme à la réponse de Joachim? –

+0

Voir mon édition, j'ai ajouté une référence à la norme C. Mais oui, vous pouvez le lancer comme proposé. – greydet

+0

Merci :) C'était explicatif. J'ai confirmé que mon compilateur avait considéré cela comme signé. J'ai donc utilisé une opération de casting et cela fonctionne très bien. Merci à tous. –

0

uint8_t est très probablement défini comme un char non signé.

char est son propre type qui se comporte exactement comme un caractère signé ou un caractère non signé (il s'agit de trois types distincts).

Dans ce cas, il se comporte comme un char signé, et vous obtenez un avertissement de conversion.

+0

Je ne pensais pas que cela dépendait du compilateur. J'ai trouvé ce lien [link] (https://developer.mbed.org/handbook/C-Data-Types). Mais si je déclare le 'Container_ID' comme non signé, je ne peux pas utiliser la fonction de chaîne que je les utilise pour un autre travail. Donc je devrais le lancer comme à la réponse de Joachim? –

+0

@abdullahcinar Oui, vous pouvez le lancer, en supposant que votre architecture a 8 bits par octet et deux complément, ce qui est presque certain qu'il le fait. – 2501

+0

Oui, je l'ai vérifié et c'est vrai. Donc je peux continuer avec ça. Merci beaucoup à vous tous qui avez une réponse à cette question. –

1
uint8     Container_ID[10]; 

Thats un entier 8 bits non signé avec des valeurs possibles de 0 à 255

char     Prefix[10]; 

Dans votre cas char signé 8 bits avec des valeurs entières de -127 à +128

Parce qu'ils ne sont pas du même type, vous obtenez un avertissement de conversion, comme vous le devriez.

1

Comme souligné dans this, la réponse aux arguments de mélange est une violation de contrainte.

Vous transmettez un argument char * non signé à une fonction qui attend un argument char * . Les deux types ne sont pas compatibles et il n'y a pas de conversion implicite de l'un à l'autre. Un compilateur conforme peut émettre un avertissement (qui compte comme un diagnostic) puis passer à générer un exécutable, mais le comportement de cet exécutable est indéfini.

Bien que cette réponse est pour char* vs non signé char* je crois même devrait tenir avec char*, uint8_t*.

1

char et uint8 ont tous deux quelque chose en commun, et c'est important: ils sont tous deux des entiers de 8 bits. Maintenant deux questions

  • est ce/ces 8 bits entiers signés, ou non signés?

Et plus important encore

  • -ce important dans votre cas?

I.e. voulez-vous envoyer à la fonction un tableau composé d'entiers pour lesquels il est important de les considérer comme signés? Par exemple, si la fonction ferait quelque chose comme ça,

if (charvalue < 0) { ... 

ou si vous voulez la fonction de prêter attention à la signedness des octets (si ce serait possible); si la fonction ferait cela, et signe importerait: l'envoi d'un 255 est positif, mais compte tenu de l'octet signé, ce serait interprété comme -1 ...

Mais cela n'a pas de sens puisque la fonction prend uint8 * (en fait à l'intérieur de la fonction, les devs ont peut-être utilisé char pour traiter les octets individuellement, et d'utiliser leur signedness, mais dans ce cas ayant une signature de fonction comme ça serait très trompeur!)

Ainsi, le E PROM SOIGNE octets non signés, et vous pouvez en toute sécurité lancer le pointeur donné à la fonction pour supprimer l'avertissement,

CyBle_StoreAppData((uint8 *)Prefix,datastack_ROM,10,0); 

ou simplement

uint8 Prefix[10]; 

si cela ne cause pas d'autres problèmes/avertissement avec le reste de votre code.