Herramientas de usuario

Herramientas del sitio


cpp-avanzado:macros

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cpp-avanzado:macros [2023/11/29 14:47]
santo
cpp-avanzado:macros [2023/11/29 15:12] (actual)
santo [El porqué de la macro forn]
Línea 30: Línea 30:
 </​code>​ </​code>​
  
-La siguiente sirve para evitar montones de errores peligrosos y muy difíciles de detectar producto de comparar enteros con y sin signo, ya que ''​.size()''​ retorna un entero sin signo, por lo que al hacerle cuentas resultados como ''​-1''​ automáticamente pasan a $2^{bits}-1$. ​Al pasar inmediatamente a entero con signo, evitamos estos problemas.+La siguiente sirve para evitar montones de errores peligrosos y muy difíciles de detectar producto de comparar enteros con y sin signo, ya que ''​.size()''​ retorna un entero sin signo, por lo que al hacerle cuentas resultados como ''​-1''​ automáticamente pasan a $2^{bits}-1$. ​El ejemplo más común sería escribir algo como ''​if (v.size()-1 >= 0)'',​ que da siempre ''​true'',​ a diferencia de ''​if (SIZE(v)-1 >= 0)''​ que se comporta como uno espera. Pasar inmediatamente a entero con signo evita problemas.
 <code cpp> <code cpp>
-#define SIZE(c) ((c).size())+#define SIZE(c) ​int((c).size())
 </​code>​ </​code>​
 +
  
  
Línea 46: Línea 47:
 #define ESTA(x,c) ((c).find(x) != (c).end()) #define ESTA(x,c) ((c).find(x) != (c).end())
 </​code>​ </​code>​
- 
-La siguiente es muy útil para utilizar con funciones de STL, donde se suele pedir un rango mediante dos iteradores, para pasar directamente una colección completa. 
-<code cpp> 
-#define ALL(c) begin(c), end(c) 
-</​code>​ 
- 
  
 Las siguientes son muy útiles para buscar y corregir errores en programas: Las siguientes son muy útiles para buscar y corregir errores en programas:
Línea 69: Línea 64:
 typedef long long tint; typedef long long tint;
 typedef long double tdbl; typedef long double tdbl;
-typedef vector<​int>​ vint; 
-typedef pair<​int,​int>​ pint; 
-typedef pair<​tint,​tint>​ ptint; 
 </​code> ​ </​code> ​
  
 +O su equivalente más moderno:
 +
 +<code cpp>
 +using tint = long long;
 +using tdbl = long double;
 +</​code> ​
 +
 +Utilizar ''​tint''​ para indicar el **t**ipo del **int** permite cambiar entre ''​int'',​ ''​unsigned'',​ ''​long long'',​ ''​unsigned long long'',​ ''​__int128'',​ ''​unsigned char'',​ etc fácilmente si se usa siempre ''​tint''​ para los "​valores"​ del programa (mientras que se usa por ejemplo ''​int''​ para los índices de arreglos y colecciones).
 ===== El porqué de la macro forn ===== ===== El porqué de la macro forn =====
  
Línea 84: Línea 84:
 <code cpp> <code cpp>
 forn(i, 10){ forn(i, 10){
-    forn (j, v.size()) {+    forn (j, SIZE(v)) {
  
     }     }
 } }
 </​code>​ </​code>​
- 
-(Comentario:​ en la declaración de la macro hay un ''​int(n)''​ que nos permite que el ''​forn''​ hasta ''​v.size()-1''​ y similares expresiones no tenga un posible bug causado por ser este valor de tipo unsigned, y de paso logra que el compilador no emita un warning por esto.) 
  
 Uno podría entusiarmarse con las macros y hacer la siguiente macro: Uno podría entusiarmarse con las macros y hacer la siguiente macro:
Línea 98: Línea 96:
 </​code>​ </​code>​
  
-**Es una muy mala idea** definir el ''​forn''​ sin pasarle la variable para indexar, porque eso nos podria ​introducir "bugs ocultos"​ por no ser suficientemente declarativos y esconder cosas en la macro. En este caso, **escondemos una declaración de variables**.+**Es una muy mala idea** definir el ''​forn''​ sin pasarle la variable para indexar, porque eso nos podría ​introducir ​muy fácilmente ​"bugs ocultos"​ por no ser suficientemente declarativos y esconder cosas en la macro. En este caso, **escondemos una declaración de variables ​visibles fuera de la macro**.
  
 Por ejemplo, este código tendría un error oculto usando esa macro Por ejemplo, este código tendría un error oculto usando esa macro
Línea 111: Línea 109:
  
 En general **el objetivo de las macros no es escribir menos caracteres, sino escribir código que evite bugs** simples por repetición o copy-paste. En general **el objetivo de las macros no es escribir menos caracteres, sino escribir código que evite bugs** simples por repetición o copy-paste.
 +
 +Otro ejemplo:
  
 <code cpp> <code cpp>
Línea 120: Línea 120:
 </​code>​ </​code>​
  
-Ese código tiene un bug no evidenteen el segundo for incrementa i en vez de j.+Ese código tiene un bug no evidente ​a simple vista: ​en el segundo for incrementa i en vez de j.
 En cambio, usando la macro forn como la definimos más arriba, sería En cambio, usando la macro forn como la definimos más arriba, sería
  
Línea 131: Línea 131:
 </​code>​ </​code>​
  
-¡Donde ese bug es simplemente **imposible** de escribir!+¡Donde ese bug es simplemente **imposible** de escribir! ​Usar ''​i''​ ambas veces sería el bug más parecido, pero si usamos las [[:​cpp-avanzado:​opciones-gcc|opciones de compilación]] recomendadas tendremos una advertencia por shadow al hacerlo, e incluso sin el warning es un bug mucho más fácil de detectar y corregir.
cpp-avanzado/macros.1701269246.txt.gz · Última modificación: 2023/11/29 14:47 por santo