2017-01-30 1 views
1

J'ai 2 définit, une avec une chaîne et une avec un nombre. Comment puis-je faire un tableau const à partir de la définir avec la chaîne et le nombre. Il y a aussi une constante supplémentaire qui devrait être dans ce tableau.C char de chaîne à tableau

Comment puis-je écrire ce code pour avoir 0x22, 0x41, 0x42, 0x42, 0x21 dans le tableau foobar, à partir des définitions FOO et BAR?

#define FOO "AB" 
#define BAR 33 

extern int rs232_write(const unsigned char *data, unsigned char count); 

const unsigned char foobar[] = 
{ 
    0x22, 
    FOO[0], /*what must i put here, this do not work*/ 
    FOO[1], 
    0x42, 
    BAR, 
}; 


int main(void) 
{ 
    rs232_write(foobar,sizeof(foobar)); 
    return 1; 
} 

En gcc, par exemple, je reçois l'erreur:

./001.c:9:5: error: initializer element is not constant 
    FOO[0], /*what must i put here*/ 
    ^

La chaîne ont toujours la même longueur. J'ai aussi essayer l'inverse:

#define FOO "AB" 
#define BAR 33 

extern int rs232_write(const unsigned char *data, unsigned char count); 

const char foobar[] = \ 
    "\x22" \ 
    FOO \ 
    "\x42" \ 
    BAR /*what must i put here, this also not work*/ 


int main(void) 
{ 
    rs232_write(foobar,sizeof(foobar)); 
    return 1; 
} 

Ici, je reçois aussi une erreur, par exemple imprime gcc:

./002.c:2:13: error: expected ‘,’ or ‘;’ before numeric constant 
#define BAR 33 
      ^

Je travaille sur un micro-contrôleur avec pas beaucoup d'espace, donc je j'aime éviter de créer le tableau à l'exécution et mon compilateur ne supporte que C89.

+0

Quel est le problème avec le code que vous nous montrez? –

+0

Voir le commentaire, le compilateur ne l'accepte pas (aussi essayé avec gcc), "error: l'élément initializer n'est pas constant" et "error: expected", 'or'; 'avant la constante numérique " – 12431234123412341234123

+0

Lorsque vous postez des questions sur les erreurs de compilation, toujours inclure les erreurs exactes (sous forme non modifiée et non modifiée et surtout * complète *) dans le corps de la question. De préférence, un copier-coller direct du journal de construction complet. –

Répondre

1

Le plus simple, en utilisant memcpy:

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

#define FOO "AB" 
#define BAR 33 

extern int rs232_write(const unsigned char *data, unsigned char count); 

unsigned char _foobar[] = 
{ 
    0x22, 
    0, 0, 
    0x42, 
    BAR, 
}; 
const unsigned char *foobar; 

int main(void) 
{ 
    foobar = (const unsigned char *)memcpy(_foobar + 1, FOO, 2) - 1; 
    rs232_write(foobar,sizeof(foobar)); 
    return 0; 
} 

Le laid, en utilisant un X Macro et compound literal:

De cette façon vous pouvez utiliser les deux premiers chiffres:

const unsigned char foobar[] = 
{ 
    0x22, 
    'A', 'B', 
    0x42, 
    33, 
}; 

ou la chaîne complète "AB"

#include <stdio.h> 

#define FOO X('A', 'B', '\0') 
#define BAR 33 

extern int rs232_write(const unsigned char *data, unsigned char count); 

const unsigned char foobar[] = 
{ 
    0x22, 
    #define X(a, b, c) a, b 
    FOO, 
    #undef X 
    #define X(a, b, c) ((char []){a, b, c}) 
    0x42, 
    BAR, 
}; 

int main(void) 
{ 
// rs232_write(foobar,sizeof(foobar)); 
    printf("%s\n", FOO); 
    return 0; 
} 

Sortie:

AB 
+0

Le memcpy(), ou dans mon cas, écris simplement les deux valeurs, est-ce que j'essayais d'éviter. mais X Macro fonctionnera. Je ne savais pas que vous pouvez créer un tableau et faire un appel de fonction en même temps. – 12431234123412341234123

+0

Ce n'est pas un appel de fonction, jetez un oeil au lien: _Ces fonctionnalités sont que les macros peuvent appeler d'autres macros, que les macros peuvent être redéfinies et qu'un appel de macro imbriqué n'est pas développé jusqu'à ce que la macro l'appelle. ses appels. –

+0

Non, je parle de quelque chose comme 'strcpy (buffer, ((char []) {0x44,0x61,0}))', que je peux appeler strcpy() avec un tableau que je ne crée pas avant, et sans une chaîne, pas sur les macros. – 12431234123412341234123

1

Cela devrait fonctionner:

#include<stdio.h> 

#define FOO 'A','B' 
#define BAR 33 

const char foobar[] = { 
    0x22, 
    FOO, 
    0x42, 
    BAR, 
    '\0' 
}; 

int main(void) 
{ 
    printf("%s\n", foobar); 
    return 0; 
} 

BTW il est très mauvais pour initialiser le tableau de cette façon, peut-être vous pouvez expliquer votre but mieux.

+0

Mais j'ai encore besoin de FOO comme chaîne à d'autres endroits, donc il est possible de créer une chaîne de const à partir de cette définition? – 12431234123412341234123

+0

Il est basé sur un protocole binaire rs232, que je ne peux pas changer, et j'ai besoin d'envoyer le nom et la version du logiciel dans un paquet (groupe de trames). – 12431234123412341234123

0

Le problème est que le compilateur ne sait pas, au moment de la compilation, où la chaîne littérale "AB" sera placée en mémoire. Sa localisation sera décidée lorsque le programme est lié ou éventuellement lorsqu'il est chargé en mémoire. Par conséquent, son utilisation n'entraînera pas une constante de temps de compilation requise pour l'initialisation de la baie foobar.

Dans ce cas, vous n'avez vraiment pas d'autre choix que d'utiliser les réglages foobar[1] et foobar[2] une fois au moment de l'exécution. Cependant, même sur un système embarqué extrêmement petit, cela n'entraînera pas beaucoup de frais généraux en mémoire ou dans le temps. Si le programme dure plus de quelques secondes, il ne sera probablement même pas mesurable.

+0

Je me fiche de l'heure, mais l'utilisation de la mémoire de mon programme est déjà un problème et j'essaye de la réduire pour ne pas avoir besoin d'activer l'optimisation. 20 octets RAM peut sembler extrêmement petit, mais vous le remarquerez avec seulement 1KiB – 12431234123412341234123

+0

@ 12431234123412341234123 L'ajout de l'initialisation au moment de l'exécution ajoutera environ deux autres instructions. Si vous n'avez que ce seul tableau, il n'y aura probablement pas de problème. Si vous avez de nombreux tableaux comme celui-ci, vous pouvez envisager d'en utiliser un seul, puis les initialiser tous lors de l'exécution. Le code est (souvent) plus petit que les données. Et pourquoi ne voulez-vous pas activer l'optimisation? Avez-vous essayé de construire avec, par exemple, '-Os'? Cela fait-il une différence? –

+0

@ 12431234123412341234123 Oh, et vous devriez probablement avoir ajouté toutes les limitations et la plate-forme cible à votre question, c'est une information très pertinente. –

1
#include <stdio.h> 
#include <stdlib.h> 

#define FOO   "ab" 
#define BAR   33 

#define STRINGIFY(x) STRINGIFY2(x) 
#define STRINGIFY2(x) #x 

const char foobar[] = "\x22" FOO "\x42" STRINGIFY(BAR); 

int main(void) 
{ 
    printf("foobar = |%s| (%ld+1 characters)\n", 
    foobar, (long) sizeof(foobar) - 1); 
    return EXIT_SUCCESS; 
} 

L'exécution de ce programme ouputs:

foobar = |"abB33| (6+1 characters) 
+0

Je veux avoir l'octet 33 ou dans ce cas le caractère '!' dans le tableau, pas les octets 51 (0x33) ou le caractère "3". Donc, il devrait imprimer "abB!" – 12431234123412341234123

+0

@ 12431234123412341234123: Alors pourquoi ne pas simplement '#define BAR" \ x21 "' ou '#define BAR"! "' '? – AlexP

+0

J'ai besoin de BAR comme un entier dans d'autres endroits. mais peut-être que je peux # définir _BAR "!" et #define BAR _BAR [0] – 12431234123412341234123