2017-04-10 2 views
1

j'ai un struct où un élément est une chaîne d'une longueur maximale de N. La définition:En C, comment faire en sorte que la longueur d'une chaîne initialisée est inférieure à celle spécifiée

typedef struct 
{ 
    const char foo[N]; 
} bar_t; 

Je me attends les utilisateurs de ce struct pour initialiser le membre foo d'une longueur de plus de N:

bar_t mybar = { .foo = "12345678" }; 

N=8. Puisque je ne peux pas contrôler tous les initialisations de bar_t, je veux compter sur le compilateur pour générer des avertissements/erreurs si bar_t.foo a une longueur supérieure à N.

Le problème est que pour tenir compte du caractère de terminaison (pour pouvoir utiliser bar_t.foo comme une chaîne normale), il me faudrait préciser bar_t.foo avec la longueur N+1

Sinon, je pourrais régler la longueur de bar_t.foo à Je dois maintenant être explicite avec la longueur de chaîne attendue (c'est-à-dire avec strn*() famille de fonctions avec N comme argument longueur maximale) lors de l'utilisation de fonctions qui attendent un caractère de terminaison.

Y at-il un moyen d'obtenir compilateur d'être restrictive sur la durée des initialisations et aussi être en mesure de traiter le terrain sans être explicite sur la longueur de chaîne max?

+0

Que diriez-vous d'une tactique inverse: toujours ajouter un caractère nul à la chaîne littérale : '.foo =" 12345678 \ 0 "'? – chux

Répondre

1

GCC ne mettre en garde contre la initialiseur chaîne plus longue que la mémoire allouée, car il est tout à fait légal. Mais vous pouvez fournir un chèque de compilation à l'aide des macros et des assertions statiques similaires à ce qui suit:

#include <stdio.h> 

#define N 6 
typedef struct 
{ 
    const char foo[N]; 
} bar_t; 

#define INIT_FOO(var, initString) \ 
    _Static_assert(sizeof(initString) < N, "Bad length!"); \ 
    bar_t var = { .foo = initString }; 

INIT_FOO(mybar, "Good"); 
//INIT_FOO(mybar, "Baaaad"); 

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

Voir en action sur ideone

+0

* puisque c'est tout à fait légal *: bien gcc a aussi des avertissements pour des constructions valides mais dangereuses donc je dirais qu'il ne l'a pas encore *:) (AFAIK). Certains autres compilateurs peuvent avoir de telles options d'avertissement. Notez que PC-lint a un message d'information (784) pour ceci: * Caractère Nul tronqué de la chaîne *. – ouah

+0

Merci. Le '_Static_assert()' pourrait être une approche raisonnable. Cela rendrait l'utilisation de la structure un peu plus lourde pour les développeurs. – theorifice