Primero, descubrí que no es posible definir el tipo de constante usando #define, ¿por qué?
¿Por qué es qué? No es verdad:
#define MY_INT_CONSTANT ((int) 12345)
En segundo lugar, ¿tiene alguna ventaja utilizar uno de ellos sobre el otro?
Si. #define
define una macro que se reemplaza incluso antes de que comience la compilación. const
simplemente modifica una variable para que el compilador marque un error si intenta cambiarla. Hay contextos en los que puedes usar a #define
pero no puedes usar a const
(aunque estoy luchando por encontrar uno usando el último clang). En teoría, un const
ocupa espacio en el ejecutable y requiere una referencia a la memoria, pero en la práctica esto es insignificante y puede ser optimizado por el compilador.
const
s son mucho más amigables con el compilador y el depurador que #define
s. En la mayoría de los casos, este es el punto primordial que debe considerar al tomar una decisión sobre cuál usar.
Solo piensa en un contexto en el que puedas usar #define
pero no const
. Si tiene una constante que desea usar en muchos .c
archivos, #define
simplemente péguela en un encabezado. Con a const
tienes que tener una definición en un archivo C y
const int MY_INT_CONST = 12345;
extern const int MY_INT_CONST;
en un encabezado. MY_INT_CONST
no se puede usar como el tamaño de una matriz de alcance estático o global en ningún archivo C, excepto en el que está definido.
Sin embargo, para constantes enteras, puede usar un enum
. De hecho, eso es lo que hace Apple casi invariablemente. Esto tiene todas las ventajas de #define
s y const
s, pero solo funciona para constantes enteras.
enum
{
MY_INT_CONST = 12345,
};
Finalmente, ¿de qué manera es más eficiente y / o más segura?
#define
es más eficiente en teoría aunque, como dije, los compiladores modernos probablemente aseguran que haya poca diferencia. #define
es más seguro porque siempre es un error del compilador intentar asignarle
#define FOO 5
FOO = 6;
const
Se puede engañar a s para que se asignen, aunque el compilador puede emitir advertencias:
const int FOO = 5;
(int) FOO = 6;
Dependiendo de la plataforma, la asignación aún puede fallar en tiempo de ejecución si la constante se coloca en un segmento de solo lectura y su comportamiento oficialmente indefinido de acuerdo con el estándar C.
Personalmente, para constantes enteras, siempre uso enum
s para constantes de otros tipos, uso a const
menos que tenga una muy buena razón para no hacerlo.
int
. Sin embargo, me sorprendería mucho si hiciera alguna diferencia en un compilador moderno.Desde un codificador C:
A
const
es simplemente una variable cuyo contenido no se puede cambiar.#define name value
, sin embargo, es un comando de preprocesador que reemplaza todas las instancias dename
withvalue
.Por ejemplo, si usted
#define defTest 5
, todas las instancias dedefTest
en su código serán reemplazadas por5
cuando compile.fuente
Es importante comprender la diferencia entre las instrucciones #define y const que no están destinadas a las mismas cosas.
const
const
se utiliza para generar un objeto del tipo solicitado que será, una vez inicializado, constante. Significa que es un objeto en la memoria del programa y se puede utilizar como de solo lectura. El objeto se genera cada vez que se inicia el programa.#define
#define
se utiliza para facilitar la legibilidad del código y futuras modificaciones. Cuando usa una definición, solo enmascara un valor detrás de un nombre. Por lo tanto, al trabajar con un rectángulo, puede definir el ancho y el alto con los valores correspondientes. Luego, en el código, será más fácil de leer ya que en lugar de números habrá nombres.Si más tarde decide cambiar el valor del ancho, solo tendrá que cambiarlo en la definición en lugar de una búsqueda / reemplazo aburrida y peligrosa en todo el archivo. Al compilar, el preprocesador reemplazará todo el nombre definido por los valores en el código. Por lo tanto, no hay tiempo que perder usándolos.
fuente
Además de los comentarios de otras personas, los errores de uso
#define
son notoriamente difíciles de depurar ya que el preprocesador se apodera de ellos antes que el compilador.fuente
Dado que las directivas de preprocesador están mal vistas, sugiero usar un archivo
const
. No puede especificar un tipo con un preprocesador porque una directiva de preprocesador se resuelve antes de la compilación. Bueno, puedes, pero algo como:#define DEFINE_INT(name,value) const int name = value;
y usarlo como
DEFINE_INT(x,42)
que sería visto por el compilador como
const int x = 42;
Puedes ver mi primer fragmento.
En general, tener una
const
directiva en lugar de un preprocesador ayuda con la depuración, no tanto en este caso (pero aún lo hace).Ambos son igualmente eficientes. Yo diría que la macro puede ser potencialmente más segura ya que no se puede cambiar durante el tiempo de ejecución, mientras que una variable sí.
fuente
const ...
en lugar de usar una macro?pre-processor directives are frowned upon
[cita requerida]He usado #define antes para ayudar a crear más métodos a partir de un método, como si tuviera algo como.
// This method takes up to 4 numbers, we don't care what the method does with these numbers. void doSomeCalculationWithMultipleNumbers:(NSNumber *)num1 Number2:(NSNumber *)num2 Number3:(NSNumber *)num23 Number3:(NSNumber *)num3;
Pero también tengo un método que solo toma 3 números y 2 números, así que en lugar de escribir dos métodos nuevos, usaré el mismo usando el #define, así.
#define doCalculationWithFourNumbers(num1, num2, num3, num4) \ doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), (num4)) #define doCalculationWithThreeNumbers(num1, num2, num3) \ doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), nil) #define doCalculationWithTwoNumbers(num1, num2) \ doSomeCalculationWithMultipleNumbers((num1), (num2), nil, nil)
Creo que es algo muy bueno tener, sé que puedes ir directamente al método y poner nil en los espacios que no quieres, pero si estás construyendo una biblioteca es muy útil. También así es como
NSLocalizedString(<#key#>, <#comment#>) NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>) NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)
están hechos.
Mientras que no creo que puedas hacer esto con constantes. Pero las constantes tienen sus ventajas sobre #define, ya que no puede especificar un tipo con un #define porque es una directiva de preprocesador que se resuelve antes de la compilación, y si obtiene un error con #define, son más difíciles de depurar entonces constantes. Ambos tienen sus ventajas y desventajas, pero yo diría que todo depende del programador al que decidas usar. He escrito una biblioteca con ambos usando #define para hacer lo que he mostrado y constantes para declarar variables constantes en las que necesito especificar un tipo.
fuente