Questions de test écrit en langage c intégré

Dans cet article, examinons les questions du test écrit du langage C embarqué. Le contenu principal de cet article est le suivant :

Pourquoi l'industrie embarquée prête-t-elle attention à l'investigation du langage C ?

Tout d'abord, résolvons d'abord le premier problème, pourquoi l'industrie embarquée prête-t-elle attention à l'investigation du langage C ? Ou pourquoi le développement embarqué est développé en langage C, et pourquoi le langage C est-il si populaire dans l'industrie embarquée parmi tant de langages de programmation ?

L'excellente portabilité du langage C et son accès direct au matériel le rendent très adapté au développement et à l'utilisation dans l'industrie embarquée. En fait, il existe des langages d'assemblage et C qui peuvent accéder directement au matériel, mais le langage d'assemblage est un langage de bas niveau et il est difficile de remplir certaines fonctions complexes.Ce langage de programmation de change est étroitement lié à l'architecture du CPU Les codes d'assemblage de l'architecture X86 et de l'architecture ARM sont différents, ce qui viole le principe de portabilité dans le développement embarqué. Cependant, l'assemblage est plus efficace que le langage C pour accéder au matériel.Par conséquent, le travail d'initialisation du matériel est généralement confié à l'assemblage, et les opérations plus complexes sont confiées au langage C.

Les limites des autres langages orientés objet et l'incapacité à faire fonctionner directement le matériel font du langage C une position et un rôle irremplaçables dans le développement embarqué.

Plusieurs sujets de questions communes de test écrit en langage C intégré

type de données

1. Utilisez la variable a pour définir les types de variables suivants

(1) Un entier

(2) Un pointeur vers un entier

(3) Un pointeur vers un pointeur, le pointeur pointé pointe vers un entier

(4) Un tableau avec dix entiers

(5) Un tableau avec 10 pointeurs, les éléments du tableau pointent vers un entier

(6) Un pointeur vers un tableau de 10 entiers

(7) Un pointeur vers une fonction qui prend un paramètre entier et renvoie un entier

(8) Un tableau de 10 pointeurs vers une fonction qui prend un paramètre entier et renvoie un entier

Répondre:

(1)int a ;

(2)int *a ;

(3)int **a ;

(4)int a[10] ;

(5)int *a[10] ;

(6)entier (*a)[10] ;

(7)int (*a)(int );

(8)int (*a[10])(int );

Analyse:

Il y a deux façons de tester cette question : l'une consiste à donner les exigences et à rédiger l'énoncé de définition par vous-même, et l'autre à donner l'énoncé de définition et à écrire la signification de la variable a par vous-même.

La solution est de maîtriser quelques principes.Tout d'abord, voici une image pour tout le monde.L'image ci-dessous décrit la priorité des opérateurs en langage C.

Ensuite, regardez quelle est l'essence de cette variable. Plus la définition de l'essence est proche, plus sa priorité est élevée. Qu'est-ce que cela signifie ? Analysons deux variables pour avoir une idée de

Un tableau avec 10 pointeurs, les éléments du tableau pointent vers un entier : int *a[10];

Un pointeur vers un tableau de 10 entiers : int (*a)[10];

D'après l'image de la priorité de l'opérateur ci-dessus, nous pouvons savoir que la priorité de [] est supérieure à *, donc dans int *a[10];, l'essence de a est un tableau, puis les membres de données stockés dans le tableau sont pointeurs et les membres de données Points vers des données entières.

Qu'en est-il de int (*a)[10] ; Ici, les parenthèses sont utilisées pour entourer *a pour souligner que l'essence de a est un type pointeur, a pointe vers un tableau et le tableau pointé a dix données entières.

Après avoir distingué les tableaux de pointeurs et les pointeurs de tableau, vous pouvez essayer d'analyser d'autres types de données complexes. Vous pouvez examiner l'exigence d'écrire une instruction de définition ou examiner l'instruction de définition pour écrire la signification de la variable a.

2. Ce qui suit est un programme C 32 bits sous Linux/Windows, veuillez calculer la valeur de sizeof

1.void func(char str[100]);  

2.int main(int argc, const char *argv[])  

3.{  

4. char str[] = "bonjour" ;  

5. car *p = str;  

6. entier n = 10 ;  

7. caractère str_fun[100] ;  

8. void*p_malloc = malloc(100);  

9. printf("sizeof(str) = %d\n",sizeof(str));  

10. printf("sizeof(p) = %d\n",sizeof(p));  

11. printf("sizeof(n) = %d\n",sizeof(n));  

12. func(str_fun);  

13. printf("sizeof(p_malloc) = %d\n",sizeof(p_malloc));  

14. retour 0 ;  

15.}  

16.void func(char str[100])  

17.{  

18. printf("sizeof(str) = %d\n",sizeof(str));  

19.}  

Répondre:

1.sizeof(str) = 6  

2.sizeof(p) = 4  

3.sizeof(n) = 4  

4.sizeof(str) = 4  

5.sizeof(p_malloc) = 4  

Analyse :

Tout d'abord, le premier calcul est la longueur en octets du tableau str, str est la longueur déterminée lors de l'attribution de la valeur initiale, et sa longueur est "hello\0" ​​​​avec une longueur totale de 6 caractères, soit 6 octets.   

Le deuxième calcul est la longueur en octets du pointeur p, quel que soit le type de données vers lequel pointe le pointeur, sa longueur en octets est de 4. 

Le troisième calcul est la longueur en octets de la variable entière n. Dans le système 32 bits, les données entières occupent 4 octets. 

Le quatrième est la longueur en octets du paramètre formel str calculé dans la sous-fonction. Pour le paramètre formel de la fonction, qu'il s'agisse d'un tableau ou d'un pointeur, son essence est un pointeur, donc sa longueur en octets est de 4 octets.   

Le cinquième calcul est la longueur en octets du pointeur p_malloc.Bien qu'il pointe vers un espace mémoire de 100 octets, son essence est toujours un pointeur, qui est toujours de 4 octets.

Mots clés et prétraitement

1. Quel est le rôle du mot-clé statique ?

répondre:

(1) Dans le corps de la fonction, la portée de la variable statique est la fonction. Contrairement à la variable auto, la mémoire de la variable n'est allouée qu'une seule fois, de sorte que sa valeur conservera toujours la dernière valeur lors de son prochain appel.

(2) Les variables globales statiques du module sont accessibles par toutes les fonctions du module, mais ne sont pas accessibles par d'autres fonctions extérieures au module.

(3) Une fonction statique dans un module ne peut être appelée que par d'autres fonctions de ce module, et le domaine d'utilisation de cette fonction est limité au module dans lequel elle est déclarée.

2. Quel est le rôle du mot clé const

répondre:

(1) Pour empêcher la modification d'une variable, vous pouvez utiliser le mot clé const. Lors de la définition de la variable, elle est généralement initialisée, car il n'y a aucune possibilité de la modifier ultérieurement.

(2) Pour les pointeurs, vous pouvez spécifier le pointeur lui-même, vous pouvez également spécifier les données pointées par le pointeur, ou les deux peuvent être spécifiés comme const.

(3) Dans la déclaration de la fonction, const peut modifier le paramètre formel, indiquant qu'il s'agit d'un paramètre d'entrée, et sa valeur ne peut pas être modifiée à l'intérieur de la fonction.

3. Quels sont les avantages de const par rapport à #define ?

répondre:

(1) La variable en lecture seule modifiée par const a un type de données spécifique et la macro n'a pas de type de données. Le compilateur peut effectuer des vérifications de sécurité de type sur la première, mais uniquement effectuer un remplacement de caractère sur la seconde sans vérification de sécurité de type.

(2) Le compilateur n'alloue généralement pas d'espace de stockage pour les variables en lecture seule const ordinaires, mais les enregistre dans la table des symboles, ce qui fait savoir lors de la compilation qu'il n'y a pas d'opération de stockage en mémoire de lecture, ce qui le rend plus efficace plus haut

4. Quelle est la différence entre l'énumération et la macro #define ?

répondre:

Vue d'ensemble des énumérations et des macros  

(1) Énumération : fait référence à l'énumération des valeurs des variables une par une, et les valeurs des variables sont limitées à la plage des valeurs énumérées   

(2) #define La définition de la macro consiste à utiliser un identifiant spécifié pour représenter une chaîne

La différence entre l'énumération et la macro #define   

(1) Les variables d'énumération peuvent être déboguées dans le compilateur, mais les constantes de macro ne peuvent pas être déboguées   

(2) Les constantes de macro #define sont simplement remplacées dans l'étape de précompilation. Les constantes d'énumération sont déterminées au moment de la compilation   

(3) Les énumérations peuvent définir un grand nombre de constantes associées à la fois, tandis que les macros #define ne peuvent en définir qu'une à la fois

5. Quelles sont les similitudes et les différences entre les macros typedef et #define ?

répondre:

(1) Similitudes : généralement, il peut être compris comme un alias pour un personnage, et un nouveau caractère est utilisé pour remplacer le caractère d'origine dans le programme.   

(2) différence  

a. La signification réelle est différente, #define est un remplacement de chaîne, typedef est un type différent pour le type

b. Il n'y a pas de point-virgule à la fin de la phrase de la définition de macro comme marque de fin, qui n'est pas effectuée pendant le processus de compilation lui-même, mais a déjà été complétée pendant le processus de prétraitement. Il est difficile de trouver des erreurs potentielles

Pointeurs et fautes de segmentation

1. Quelle est la relation entre les pointeurs, les tableaux et les adresses ?

répondre:

(1) Le tableau est stocké dans une unité de mémoire continue, et le nom du tableau est la première adresse de l'unité de mémoire continue, et l'adresse de l'unité de mémoire est un pointeur, de sorte que le nom du tableau est également un pointeur.

(2) Le tableau est composé de plusieurs éléments de tableau, et la taille de la mémoire continue occupée par les éléments est différente selon le type du tableau. La première adresse d'un élément d'un tableau est la première adresse de l'unité de mémoire continue qu'il occupe.

(3) Une variable pointeur peut pointer vers un tableau ou un élément de tableau. Affectez le nom du tableau ou l'adresse du premier élément du tableau au pointeur, et le pointeur pointe vers un tableau. Si vous souhaitez que la variable de pointeur pointe vers le i-ème élément, vous pouvez lui affecter la première adresse du i élément.

2. Comment utiliser des pointeurs pour représenter des tableaux multidimensionnels

répondre:

Par exemple : supposez que a est le nom d'un tableau à deux dimensions et que a représente la première adresse de l'ensemble du tableau à deux dimensions.

n a+i, a[i], (a+i), &a i sont équivalents,  

a[i]+j=(*(a+i)+j) La valeur de cet élément est égale à *(*(a+i)+j)

3. Comment les pointeurs secondaires sont-ils appliqués aux tableaux unidimensionnels ?

répondre:

int a=[10],*p1,**p2,i ;

p1=a ;

p2=&p1;

a[i]=*(*p2+i)=* (p1+i)=*(a+i)

Fonctions liées aux chaînes

1.size_t strlen(const char *s); 

Fonction : Calculer la longueur de la chaîne 

Paramètres : s : tableau de caractères 

Valeur de retour : renvoie la longueur réelle de la chaîne, à l'exception de '\0'

1.//Réalisez-le vous-même

2.int my_strlen(const char *s)  

3.{  

4. car * sc;  

5. pour (sc = s; *sc != '\0'; ++sc);  

6. retour sc - s;  

7.}  

2.char *strcpy(char *dest, const char *src); 

Fonction : copier les données de src vers dest 

Paramètres : dest : tableau de caractères de destination src : tableau de caractères source 

Valeur de retour : le tableau de caractères copié 

Description : Le tableau de caractères dest 1 doit être suffisamment grand 

Avant la connexion, les deux chaînes se terminent par '\0' ; après la connexion, le '\0' de dest est annulé et '\0' est ajouté à la fin de la nouvelle chaîne

1.//Réalisez-le vous-même  

2.char *my_strcpy(char *dest, const char *src)  

3.{  

4. int je ;  

5. while(src[i] != '\0')  

6. {  

7. dest[i] = src[i] ;  

8. je++ ;  

9. }  

dix.  

11. dest[i] = '\0' ;  

12. destination retour ;  

13.}  

3.char *strcat(char *dest, const char *src); 

Fonction : ajouter les données de src à dest 

Paramètres : dest : tableau de caractères de destination src : tableau de caractères source 

Valeur de retour : Identique à la destination finale 

Explication : le tableau de caractères 1 doit être suffisamment grand 

Avant la connexion, les deux chaînes se terminent par '\0' ; après la connexion, '\0' dans la chaîne 1 est annulé et '\0' est ajouté à la fin de la nouvelle chaîne

1.//Réalisez-le vous-même  

2.char *strcat(char *dest, const char *src)  

3.{  

4. int je = 0, j = 0 ;  

5. tandis que(dest[i] != '\0'){  

6. je++ ;  

7. }  

8. tandis que(src[j] != '\0'){  

9. dest[i++] = src[j++] ;  

dix. }  

11. dest[i] = '\0' ;  

12. destination retour ;  

13.}  

4.int strcmp(const char *s1, const char *s2); 

Fonction : comparer la longueur de deux chaînes 

Valeur de retour : si chaîne 1< chaîne 2, renvoie un entier négatif 

Si chaîne 1 > chaîne 2, renvoie un entier positif 

Si chaîne1 == chaîne2, renvoie zéro 

illustrer: 

Comparez les deux chaînes une par une de gauche à droite (code ASCII), jusqu'à ce qu'un caractère différent ou '\0' soit rencontré 

Vous ne pouvez pas utiliser "==" pour la comparaison de chaînes, vous devez utiliser strcmp

1.//Réalisez-le vous-même  

2.int my_strcmp (const char *s1, const char *s2)  

3.{  

4. int ret;  

5. while ((ret = *(caractère non signé *) s1 - *(caractère non signé*) s2++) == 0 && *s1++);  

6. retour ret;  

7.}  

liste liée

La chose la plus compliquée dans la liste liée est la liste liée circulaire bidirectionnelle. Montrez-moi la liste liée circulaire bidirectionnelle. Je crois que si la liste liée circulaire bidirectionnelle peut être bien comprise, la liste liée unidirectionnelle est aucun problème.

1. Liste chaînée circulaire bidirectionnelle

1.//listeliens.h  

2.#ifndef __LINKLIST_H__  

3.#définir __LINKLIST_H__  

4.#inclure   

5.#inclure   

6.//Liste circulaire doublement liée  

7.typedef int type de données ;  

8.typedef struct dnode{  

9. données de type de données ;  

10. struct dnode *prior ;  

11. struct dnode *suivant ;  

12.}DListeLiens, *DListeLiens_p ;  

13.DLinkList_p creat_dlinklist(void);  

14.DLinkList_p getnode_dlinklist(DLinkList_p D, int pos);  

15.int insert_dlinklist(DLinkList_p D, valeur du type de données, int pos);  

16.void show_dlinklist(DLinkList_p D);  

17.int delete_dlinklist(DLinkList_p D, int pos);  

18.#endif  

1.// liste de liens.c  

2.#include "listeliens.h"  

3.DLinkList_p creat_dlinklist(void){  

4. DLinkList_p D = NULL ;  

5. D = (DLinkList *)malloc(sizeof(DLinkList));  

6. si(NULL == D){  

7. printf("erreur malloc !\n");  

8. renvoie NULL ;  

9. }  

10. D->données = 0 ;  

11. D->prior = D ;  

12. D->suivant = D ;  

13. retour D ;  

14.}  

15.DLinkList_p getnode_dlinklist(DLinkList_p D, int pos){  

16. if(NULL == D){ printf("D est NULL"); renvoie NULL ; }  

17. if(pos < 0){ printf("pos error!\n"); renvoie NULL ; }  

18. int je = 0 ;   

19. DLinkList_p p = D->suivant ;  

20. tandis que( p != D && je < pos){  

21. p = p->suivant ;  

22. je++ ;  

23. }  

24. if(p == D){ printf("pos > longueur\n"); renvoie NULL ; }  

25. si(je == pos){ renvoie p ; }  

26. printf("pos > longueur !\n");  

27. renvoie NULL ;  

28.}  

29.//Insérer une fonction  

30.int insert_dlinklist(DLinkList_p D, valeur du type de données, int pos){  

31. DLinkList_p nouveau = NULL ; DLinkList_p Q = NULL ;  

32. if(NULL == D){ printf("D est NULL\n"); retour -1 ; }  

33. if(pos < 0){ printf("pos error!\n"); retour -1 ; }  

34. sinon si( D->suivant == D ){ Q = D ; }  

35. else{ Q = getnode_dlinklist(D, pos); }  

36. if( NULL == Q ){ printf("Q get NULL\n"); retour -1 ; }  

37.      

38. new = (DLinkList *)malloc(sizeof(DLinkList));  

39. si(NULL == nouveau){  

40. printf("erreur malloc !\n");  

41. retour -1 ;  

42. }  

43. nouveau->données = valeur ;  

44. nouveau->suivant = Q ;  

45. nouveau->prior = Q->prior ;  

46. ​​Q->précédent->suivant = nouveau ;  

47. Q->antérieur = nouveau ;  

48. retour 0 ;  

49.}  

50.//Supprimer  

51.int delete_dlinklist(DLinkList_p D, int pos){  

52. DLinkList_p del = NULL ;  

53. if(NULL == D){ printf("D est NULL\n"); retour -1 ; }  

54. if(pos < 0){ printf("pos error!\n"); retour -1 ; }   

55. else{ del = getnode_dlinklist(D, pos); }  

56. if( NULL == del ){ printf("Q obtient NULL\n"); retour -1 ; }  

57.      

58. del->prior->next = del->next ;  

59. del->suivant->prior = del->prior ;  

60. libre(del);  

61. Suppr = NULL ;  

62. retour 0 ;  

63.}  

64.void show_dlinklist(DLinkList_p D){  

65. if(NULL == D){ printf("D est NULL\n"); retour; }  

66. DLinkList_p p = D->suivant ;  

67. tandis que(p != D){  

68. printf("%d\n", p->données);  

69. p = p->suivant ;  

70. }  

71.}  

L'Internet des Objets embarqué a besoin d'apprendre beaucoup. Ne vous trompez pas d'itinéraire et de contenu, ce qui fera augmenter votre salaire !

Partagez un forfait de données avec tout le monde, environ 150 G. Le contenu d'apprentissage, les écritures face à face et les projets qu'il contient sont relativement nouveaux et complets ! (Cliquez pour trouver un petit assistant à recevoir)

Je suppose que tu aimes

Origine blog.csdn.net/m0_70911440/article/details/131591260
conseillé
Classement