C++17 cr�e une utilisation pratique de l'op�rateur d'indexation de tableau r�trograde, par Raymond Chen, Senior Software Engineer chez Microsoft
Il est bien connu que si a est un pointeur ou un tableau et i un entier, alors a[i] et i[a] sont �quivalents en C et C++, ce qui donne lieu � des hilarit�s telles que :
Il y a tr�s peu d'utilisation pratique pour cette �quivalence, � part pour faire des farces aux gens�.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7 void haha() { int a[5]; for (i = 0; i < 5; i++) { i[a] = 42; } }
Et puis C++17 est arriv�.
L'un des changements apport�s au langage de base en C++17 a �t� le renforcement de l'ordre des r�gles d'�valuation, formellement connu sous le nom de s�quen�age. Nous avions d�j� rencontr� ce probl�me en �tudiant un crash qui semblait concerner une op�ration std::move.
L'une des op�rations qui a re�u un ordre d'�valuation d�fini est l'op�rateur d'indice. � partir de C++17, a[b] �value toujours a avant d'�valuer b.
Par cons�quent, si votre �valuation de l'index peut avoir un effet secondaire sur l'�valuation du pointeur, vous pouvez inverser l'ordre pour forcer l'index � �tre calcul� en premier.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 int* p; int index(); auto test() { return p[index()]; } // Compiled as C++14 sub rsp, 40 call index ; call index first movsxd rcx, rax mov rax, p ; then fetch p mov eax, [rax + rcx * 4] add rsp, 40 ret // Compiled as c++17 push rbx sub rsp, 32 mov rbx, p ; fetch p first call index ; then call index movsxd rcx, rax mov eax, [rbx + rcx * 4] add rsp, 32 pop rbx ret
�tonnez vos amis ! D�concertez vos ennemis !
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4 auto test() { return index()[p]; }
Bavardage en prime : clang impl�mente cela correctement, mais msvc (v19) et gcc (v13) se trompent d'ordre et chargent p avant d'appeler index. (Par comparaison, icc se trompe aussi, mais dans l'autre sens : Il charge toujours p en dernier).
� Une autre utilisation pratique est de contourner toute surcharge possible de l'op�rateur [], comme indiqu� dans le chapitre 14 de Imperfect C++ :
En inversant l'ordre dans 0[a], cela permet de contourner une �ventuelle surcharge de a[].
Code : S�lectionner tout - Visualiser dans une fen�tre � part #define ARRAYSIZE(a) (sizeof(a) / sizeof(0[a]))
Cependant, cette m�thode n'est pas infaillible. Il suffit de cr�er un imb�cile plus astucieux : Si v est un pointeur ou un objet convertible en pointeur, alors ce pointeur ira volontiers � l'int�rieur de 0[...].
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2 std::vector<int> v(5); int size = ARRAYSIZE(v); // compiler error
Heureusement, vous n'avez pas besoin d'astuces macro. Vous pouvez laisser les fonctions constexpr du C++ faire le travail � votre place :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12 struct Funny { operator int*() { return oops; } int oops[5]; int extra; }; Funny f; int size1 = ARRAYSIZE(f); // oops: 6 int* p = f; int size2 = ARRAYSIZE(p); // oops: 1
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2 template<typename T, std::size_t N> constexpr std::size_t array_size(T(&)[N]) { return N; }
Et vous ?
Qu'en pensez-vous ?
Voir aussi :
Les travaux sur la norme C++ 23 sont termin�s et cette nouvelle version porte le nom de code "Pandemic Edition", C++ 23 cherche � am�liorer la vitesse de compilation et l'hygi�ne du code
Zig, pr�sent� comme une alternative moderne au C, fait son apparition dans le top 50 de l'indice Tiobe des langages les plus populaires. Carbon, l'alternative C++ de Google, n'est class� que 168e
C++ vs Rust : une comparaison pratique de la vitesse de compilation et de test des deux langages de programmation, par Matthew Glazar, ing�nieur en g�nie logiciel




Qu'en pensez-vous ?
R�pondre avec citation





?



?

Partager