Langage C 8 questions du test du stylo pointeur Dachang - saisir le pointeur

Pour la précision des questions et l'habitude de notre processus d'apprentissage général, tous les codes de question ici sont exécutés sous l' environnement X86 (plate-forme 32 bits) .

Sujet un :

#include <stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}
//程序的结果输出什么?

Étudions d'abord ce qui est stocké dans la variable de pointeur ptr. &a+1 signifie retirer toute l'adresse et sauter en arrière de la taille du type de tableau, c'est-à-dire pointer vers l'espace de la taille du type de tableau derrière le dernier élément 5 du tableau .

Mais nous ne pouvons pas donner cette adresse à la variable de pointeur ptr, car les types sont différents (&a+1 est un type de pointeur de tableau, prt est un type de pointeur entier), donc avant (&a+1) (int* ) pour lancer le genre . Nous déterminons donc ce qui est stocké dans la variable de pointeur ptr.

Alors maintenant, regardez la section de sortie. *(a+1) est relativement simple, a est l'adresse du premier élément, a+1 est l'adresse du deuxième élément, et déréférencez-le pour obtenir le deuxième élément 2, ce qui est une réponse indiscutable. Pour *(ptr-1), nous connaissons l'adresse stockée dans ptr, et nous savons que ptr est un pointeur entier , ptr-1 équivaut à sauter en avant de la taille d'un type entier, c'est-à-dire pointer vers la position de le dernier élément 5 du tableau . Déréférencez-le pour obtenir l'élément 5 .

 

 Le résultat de sortie final est donc : 2, 5 .

Sujet deux :

#include <stdio.h>

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}
//程序最后输出什么?

Nous prêtons attention à la définition de la structure et définissons une variable de pointeur de structure p .

p+0x1 est très simple, 0x1 vaut 1, juste écrit au format hexadécimal. C'est la même chose que le calcul de pointeur auquel nous sommes souvent habitués, p est un pointeur de structure, alors p+1 devrait sauter en arrière de la taille d'un type de structure, c'est-à-dire pointer vers la position de l'espace de structure après l'espace de structure . Et nous savons que p est une variable globale, et la variable globale est initialisée à 0 par défaut , alors nous pouvons savoir que p=0, p+1=20. Et %p est un format d'impression hexadécimal, donc le résultat est : 00000014 .

(unsigned long)p + 0x1 semble plus simple. Le type p est converti en un entier long, cela signifie que p n'est plus un pointeur et que le 0 qu'il stocke est un nombre au sens simple. Donc 0 + 0x1 est égal à 00000001 .

(unsigned int*)p + 0x1 est également très simple. p était à l'origine un pointeur de structure, mais maintenant il est converti en un pointeur entier, ce qui signifie que la foulée de p passe de 20 octets à 4 octets lors de l'ajout et de la soustraction d'entiers . Alors p=0, p+1=4 est hors de doute. Le résultat de la sortie est : 00000004 .

 Sujet trois :

#include <stdio.h>

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}
//程序的结果输出什么?

L'analyse de ptr1 n'est pas différente de celle du titre 1. ptr1 stocke l'adresse de la taille du type tableau derrière le dernier élément du tableau . Et ptr1 est un pointeur entier.

ptr1[-1] peut être réécrit comme *(ptr-1), car nous avons dit que tant que les opérations des indices de tableau sont des opérations de pointeur, les opérations des indices de tableau ne sont que des raccourcis pour les opérations de pointeur . Ensuite, ptr1[-1] doit pointer vers le dernier élément 4 du tableau et le déréférencer pour obtenir le résultat de sortie 00000004 .

(int*)((int)a+1) Comment le comprendre ? a est le nom du tableau, puis il pointe vers l'adresse du premier élément du tableau, puis le contraint au type, puis l'adresse stockée dans a est un nombre au sens simple , nous ajoutons 1 à ce nombre , puis forcez le type Converti en un pointeur entier et stocké dans ptr2. C'est-à-dire que a est l'adresse pointant vers le premier élément du tableau, (int)a+1 représente le numéro d'adresse + 1, et le numéro d'adresse + 1 signifie que si c'est un pointeur, il pointera vers le octet suivant . Ensuite, convertissez-le en un pointeur entier, puis l'adresse pointée par ptr2 est :

 

Déréférencez-le à nouveau pour trouver le contenu de l'espace dans le carré rouge. Parce qu'il est stocké en petit boutiste, le résultat de sortie est : 02000000 .

Il convient de noter que le format d'impression utilisé dans cette question est %x, qui est hexadécimal, et le 0 devant les chiffres significatifs sera omis .

Sujet quatre :

#include <stdio.h>

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}
//程序的结果输出什么?

Tout d'abord, observons que trois expressions à virgule sont stockées dans le tableau à deux dimensions a Je pense que quelqu'un va marcher sur la fosse ici. C'est-à-dire trois expressions de virgule, alors le contenu du tableau à deux dimensions a doit être 1, 3, 5, 0, 0, 0 (le tableau a a 6 éléments, et le contenu n'est pas suffisant et automatiquement rempli de 0).

 

Après avoir compris ce que le tableau à deux dimensions stocke, étudions ce qu'est a[0]. a[0] est le premier élément du tableau à deux dimensions, qui est un tableau, c'est-à-dire que la variable de pointeur p stocke le premier élément du tableau à deux dimensions, qui est un tableau à une dimension, c'est-à-dire , prenez un nom de tableau . Alors p[0] est facile à comprendre, p est un nom de tableau et p[0] est le premier élément du tableau, qui est 1. Donc sortie 1 .

 

 

Sujet cinq :

#include <stdio.h>

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}
//程序的结果输出什么?

Nous pouvons voir que le pointeur de tableau p stocke l'adresse du premier élément du tableau à deux dimensions a, ce qui n'est pas difficile à analyser.Le tableau pointé par p a le même contenu de stockage que le tableau a, mais l'allocation de mémoire est différent .

Nous superposons ces deux espaces :

 On peut voir que la différence entre &p[4][2] et &a[4][2] est de 4 éléments , mais parce que la position d'adresse de &p[4][2] est relativement faible, les deux soustractions sont négatives nombre, c'est -4 . Mais nous voulons imprimer comme %p, %p est un nombre non signé, nous savons donc que le résultat doit être un très grand nombre hexadécimal. Alors la négation originale de -4 est :

Ainsi, la sortie du premier est : fffffffc .

Nous savons qu'en soustrayant des pointeurs (adresses), nous obtenons le nombre d'éléments qui diffèrent, comme nous l'avons mentionné ci-dessus. Alors %d est un format d'impression signé, donc la sortie est -4 .

 

Sixième sujet :

#include <stdio.h>

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}
//程序的结果输出什么?

Le résultat de *(ptr1-1) est 10 , ne devrait-il pas être correct ?

*(aa+1) peut être réécrit comme aa[1], qui est le deuxième élément d'un tableau à deux dimensions, qui est un tableau à une dimension, c'est -à -dire qu'un nom de tableau est obtenu . Le nom du tableau est forcé d'être converti en un pointeur entier et stocké dans la variable de pointeur ptr2. A ce moment, la position de pointage spécifique de ptr2 est connue. (Les tableaux bidimensionnels sont stockés de manière contiguë dans l'espace mémoire !)

*(ptr2-1) consiste à sauter ptr2 vers l'avant de la taille d'un type entier, et à déréférencer, c'est-à-dire que l'élément 5 est trouvé, donc le résultat de sortie est 5

Sujet sept :

#include <stdio.h>

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}
//程序的结果输出什么?

Le tableau de pointeurs a stocke trois constantes de chaîne ( les constantes sur les chaînes ont été introduites dans les blogs précédents), et le pointeur secondaire pa est utilisé pour pointer vers ce tableau (char** pa=a;), ce qui indique que pa La variable stocke l'adresse du premier élément du tableau a . pa++ pointe vers le deuxième élément du tableau, *pa obtient sans aucun doute l'adresse du premier élément de la constante de chaîne "at", puis l'imprime via %s pour obtenir at .

Sujet huit :

#include <stdio.h>

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}
//程序的结果输出什么?

 Analysons d'abord ce qui est stocké dans c, cp et cpp. Il y a quatre constantes de chaîne stockées dans le tableau de pointeurs c . Le tableau de pointeurs cp stocke les adresses de quatre constantes de chaîne . Le pointeur de troisième niveau cpp stocke l'adresse du premier élément du tableau de pointeurs cp . Ensuite, le croquis peut être dessiné comme:

 

**++cpp , en raison de l'associativité , nous devons d'abord calculer ++cpp, puis cpp pointe vers l'adresse du deuxième élément de cp, puis déréférence pour obtenir le deuxième élément de cp, qui est à nouveau Point vers le troisième élément de c, puis déréférencez pour obtenir le troisième élément de c, qui est l'adresse du premier caractère de la constante de chaîne "POINT", et imprimez le POINT sous la forme %s . Il faut noter que l'opération ++ est impliquée dans l'opération de cpp, donc l'opération suivante commencera à partir de la position calculée .

 *--*++cpp+3 , ou calculez d'abord ++cpp, à ce moment cpp pointe vers l'adresse du troisième élément de cp, puis déréférencez pour obtenir c+1, puis --, c+1 devient c , puis déréférencer pour obtenir l'adresse du premier élément de c. A partir de cette adresse +3, vous obtenez l'adresse du quatrième caractère de la constante de chaîne "ENTER", puis l'imprimez sous la forme %s à obtenir ER .

 *cpp[-2]+3 peut être réécrit comme *(*(cpp-2))+3 , c'est-à-dire qu'à ce moment cpp pointe sur l'adresse du premier élément de cp, et le déréférencement donne c+3 , c+3 est Point sur l'adresse du quatrième élément de c, déréférencer pour obtenir le quatrième élément de c, cet élément est l'adresse du premier élément de la constante de chaîne "FIRST", sur la base de cette adresse +3 obtiendra la chaîne constante premier élément Une adresse à quatre caractères à partir de laquelle %s est imprimé pour obtenir ST . ( Pour le moment, cpp n'a pas de fonctionnement réel )

 cpp[-1][-1]+1 peut être réécrit comme *(*(cpp-1)-1)+1, à ce moment cpp pointe vers l'adresse du second élément de cp, déréférence pour obtenir c+2 , puis - 1 Obtenir c+1, qui pointe sur l'adresse du deuxième élément de c, déréférencer pour obtenir le deuxième élément de c, cet élément est l'adresse du premier élément de la chaîne constante "NEW", puis + 1 pointe vers L'adresse du deuxième caractère de la constante de chaîne, EW est obtenue en l'imprimant sous la forme %s .

 

 

Je suppose que tu aimes

Origine blog.csdn.net/weixin_59913110/article/details/125597828
conseillé
Classement