Meilleures pratiques pour l'initialisation de tableaux C avec des données de fichiers externes et formes d'onde
Apprenez à initialiser des tableaux C à l'aide de fichiers texte externes
Ce guide explique comment remplir des tableaux dans un programme C avec des données stockées dans des fichiers texte séparés. Les valeurs ne sont pas intégrées dans le code source ; elles sont chargées au moment de la compilation. Nous couvrons les tableaux unidimensionnels et multidimensionnels, montrons comment contrôler si le tableau réside en RAM ou en mémoire non volatile, et illustrons comment choisir entre plusieurs fichiers de données pour l'initialisation.
Les exemples ciblent un microcontrôleur ARM 32 bits et sont compilés avec GCC. Tous les extraits utilisent le C standard et fonctionnent avec ce compilateur.
Bases de l'initialisation d'un tableau
Lorsque vous déclarez un tableau en C, vous pouvez fournir une liste de valeurs — appelées initialiseurs — entre accolades. Par exemple :

Si vous omettez la taille entre crochets, le compilateur la déduit du nombre d'initialiseurs. Si le tableau est déclaré plus grand que la liste d'initialiseurs, les éléments restants prennent la valeur zéro par défaut. Fournir plus d'initialiseurs que la taille déclarée déclenche une erreur de compilation.
Espaces blancs
Les initialiseurs sont séparés par des virgules, et vous pouvez ajouter librement des espaces blancs — espaces, tabulations, retours à la ligne, retours chariot, tabulations verticales ou sauts de page — entre eux. En C, les instructions peuvent s'étendre sur plusieurs lignes ; cela est particulièrement utile pour les grands tableaux qui peuvent remplir plusieurs pages de code source.

Initialisation d'un tableau à partir d'un fichier
Le préprocesseur C peut inclure des fichiers texte arbitraires à l'aide de la directive #include. Cette fonctionnalité n'est pas limitée aux fichiers d'en-tête ou source ; tout fichier texte brut est acceptable. Un simple fichier contenant des nombres, des virgules et des espaces blancs peut être utilisé pour initialiser un tableau :

Le fichier inclus doit être du texte brut — pas de formatage enrichi, d'en-têtes ou autres artefacts. Un exemple rapide créé avec le Bloc-notes Windows ressemble à ceci :

Lors de la compilation, le tableau apparaît en mémoire comme indiqué dans la capture du débogueur. Dans ce cas, le tableau réside en RAM, indiqué par les adresses élevées dans la colonne « Location ».

Stockage d'un tableau en mémoire non volatile et sélection d'un fichier de données
Dans l'exemple ci-dessus, le tableau est une variable globale sans placement explicite. Le compilateur suppose qu'il peut être modifié à l'exécution, il le place donc en RAM. Les valeurs initiales résident en mémoire non volatile (généralement Flash) et une routine de démarrage les copie en RAM. Si le tableau est vraiment constant, le déclarer const indique au compilateur de le garder uniquement en Flash, économisant la précieuse RAM. La capture suivante montre l'effet : le « Location » du tableau pointe vers des adresses Flash basses.

Vous pouvez utiliser les directives #define et #if pour basculer entre stockage en RAM et Flash, ou pour choisir différents fichiers de données pour l'initialisation. Par exemple, le code suivant permet de choisir l'emplacement de stockage au moment de la compilation :

La construction #if est un exemple classique d'inclusion conditionnelle. Elle détermine si le qualificateur const est appliqué en fonction d'un indicateur de compilation.
De même, vous pouvez sélectionner conditionnellement quel fichier fournit les données initiales :

Test avec un grand tableau
Pour valider la technique, j'ai utilisé une forme d'onde de bruit de 10 000 échantillons stockée dans un fichier CSV. Le graphique ci-dessous montre la forme d'onde, tandis que la déclaration montre comment les données sont incorporées dans le programme :


Le fichier CSV original ne comportait pas de virgules après chaque valeur. En utilisant une recherche/remplacement par expression régulière (recherche \R et remplacement par ,\R), des virgules ont été ajoutées à toutes les 10 000 entrées en une seule opération.
Le tableau résultant est visible dans le débogueur, proprement groupé par lignes de 100 éléments.

Tableaux multidimensionnels
Lorsque vous travaillez avec des données à deux ou trois dimensions, rappelez-vous que C stocke les tableaux en ordre par lignes. Par exemple, un tableau uint16_t test[2][3] est disposé en mémoire comme suit :
[0,0] [0,1] [0,2] [1,0] [1,1] [1,2]
L'accès aux éléments consécutifs selon l'indice le plus à droite est plus rapide car les données sont contiguës. Si vous avez besoin de deux vecteurs de 1 000 échantillons, déclarez test[2][1000] pour maximiser la convivialité du cache.
L'initialiseur pour un tableau bidimensionnel est normalement groupé avec des accolades imbriquées :

Cependant, vous pouvez omettre les accolades externes ; le compilateur remplit alors le tableau de gauche à droite. Il émet un avertissement : missing braces around initializer. Tant que le nombre total de valeurs correspond à la taille du tableau, le code compile.

Pour répartir les données sur plusieurs fichiers, incluez simplement chaque fichier en séquence, en enveloppant toute la liste avec une paire d'accolades :

Initialisation de tableaux dans les unions
Une union permet à différents types de partager la même mémoire. Par exemple, une union contenant un vecteur unidimensionnel et une matrice bidimensionnelle occupe le même espace d'adressage :

Lors de l'initialisation, le compilateur remplit d'abord le premier membre. Si l'ordre est inversé, vous pouvez voir un avertissement car la liste d'initialiseurs n'est pas entièrement entre accolades. Des doubles accolades autour du #include assurent le groupement correct :
Le fichier de données pour l'union ressemble à ceci :

En mémoire, vector et matrix commencent au même emplacement, comme le montre le débogueur :

Connaissez-vous une autre méthode pour initialiser un tableau multidimensionnel à partir d'un seul fichier numérique ? Partagez vos idées dans les commentaires.
Astuce bonus : les chaînes de caractères
L'initialisation d'une chaîne à partir d'un fichier externe nécessite que les guillemets soient à l'intérieur du fichier lui-même. Un #include direct à l'intérieur du littéral de chaîne casse le compilateur. Placez plutôt les guillemets dans le fichier et incluez-le comme ceci :

La chaîne résultante réside en RAM, comme l'illustre la capture d'écran.

Ces exemples sont théoriques et devraient fonctionner avec n'importe quel compilateur C standard. Si vous rencontrez des particularités spécifiques à un compilateur, faites-le nous savoir dans les commentaires.
Source fournie.
Embarqué
- La révolution du Cloud : Comment le Cloud Computing transforme l'IT, la sécurité et les carrières
- STMicroelectronics Lance STM32Cube.AI : Réseaux Neuronaux Embarqués pour Terminaux Edge
- DATA MODUL lance moniteurs open-frame ultra-lumineux 21,5" et 31,5" avec EasyTouch pour extérieur/intérieur
- Microchip introduit ADCs Delta-Sigma 24-bit & 16-bit avec taux données 153,6 kSPS
- Contrinex 2020 : capteurs cloud-ready et rideaux lumineux Bluetooth pour la sécurité
- Les tableaux en C++ : Déclaration, initialisation et techniques avec pointeurs
- Maîtriser l'allocation de tableaux dynamiques en C++ : Guide pratique avec exemples de code
- Donner vie à l'IoT avec IBM et Tech Data – Partie 2
- Transformer l'IoT en réalité : insights Tech Data et IBM – Partie 1