Pregunta

Tengo un C proyecto donde todo el código está organizado en *.c/*.h archivo de pares, y necesito definir un valor constante en un archivo, que será sin embargo también se utiliza en otros archivos.¿Cómo debo declarar y definir este valor?

Debe ser como static const ... en el *.h archivo?Como extern const ... en el *.h archivo y definidas en el *.c archivo?En ¿qué importa si el valor no es una primitiva de tipo de datos (int, double, etc), pero un char * o un struct?(Aunque en mi caso es un double.)

La definición de cosas en su interior *.h los archivos no parece una buena idea en general;uno debe declarar las cosas en el *.h archivo, pero definen en el *.c archivo.Sin embargo, la extern const ... enfoque parece ineficiente, ya que el compilador no iba a ser capaz de poner en línea el valor, en lugar de tener que acceder a través de su dirección todo el tiempo.

Supongo que la esencia de esta pregunta es:Se debe definir static const ... los valores en *.h los archivos en C, con el fin de utilizarlos en más que un lugar?

¿Fue útil?

Solución

La regla que se sigue es sólo para declarar las cosas en H archivos y definir en C archivos.Usted puede declarar y definir en un solo archivo C, suponiendo que sólo se utilizará en el archivo.

Por declaración, me refiero a notificar el compilador de su existencia, pero no asignar el espacio para ello.Esto incluye #define, typedef, extern int x, y así sucesivamente.

Definiciones de asignar valores a las declaraciones y asignar espacio para ellos, tales como int x y const int x.Esto incluye definiciones de función;incluyendo estos en los archivos de encabezado a menudo desperdicio de espacio de código.

He visto a muchos programadores junior confundirse cuando se ponen const int x = 7; en un archivo de encabezado y después se preguntan por qué obtener un enlace de error para x ser definido más de una vez.Creo que, como mínimo, usted necesitará static const int x para evitar este problema.

Yo no estaría demasiado preocupado acerca de la velocidad del código.El principal problema con los ordenadores (en términos de velocidad y costo) hace tiempo que pasó de la velocidad de ejecución de la facilidad de desarrollo.

Otros consejos

Si usted necesita constantes (real, compilar constantes de tiempo) puede hacerlo de tres maneras, de ponerlos en los archivos de cabecera (no hay nada de malo con eso):

enum {
    FOO_SIZE = 1234,
    BAR_SIZE = 5678
};

#define FOO_SIZE 1234
#define BAR_SIZE 5678

static const int FOO_SIZE = 1234;
static const int BAR_SIZE = 5678;

En C++, que tienden a usar la enumeración manera, ya que puede aplicarse en un espacio de nombres.Para C, puedo usar la macro.Este basicially se reduce a una cuestión de gusto, aunque.Si usted necesita de punto flotante constantes, no puede usar la enumeración más.En C++ yo uso la última forma, la static const doble, en ese caso (nota: en C++ estática sería redundante entonces;serían estáticas de forma automática, ya que son const).En C, me gustaría que el uso de las macros.

Es un mito que utilizar el tercer método se ralentizará el programa de ninguna forma.Yo prefiero la enumeración ya que los valores que te dan son rvalues usted no puede conseguir su dirección, la que considero como una mayor seguridad.Además, hay mucho menos de la caldera de la placa código escrito.El ojo se concentra en las constantes.

¿Realmente tiene una necesidad de preocuparse por la ventaja de línea? A menos que usted está escribiendo código embebido, se adhieren a la legibilidad. Si realmente es un número mágico de algo, que haría uso de una definición; Creo que const es mejor para cosas como las cadenas de versión const y la modificación de los argumentos de la función de llamada. Dicho esto, la definen en .c, declarar en .h regla es sin duda una convención bastante universalmente aceptada, y no me romperlo sólo porque podría guardar una búsqueda de memoria.

Como regla general, no se define cosas como static en un encabezado. Si lo hace #define definir variables en un encabezado, cada archivo que utiliza el encabezado obtiene su propia copia privada de todo lo que se declaró extern, que es la antítesis de la SECO principio: don 't repetirse .

Por lo tanto, se debe utilizar una alternativa. Para los tipos de enteros, utilizando enum (definido en una cabecera) es muy potente; funciona bien con los depuradores también (aunque los mejores depuradores pueden ser capaces de ayudar con const valores de macro también). Para los tipos no enteros, una declaración <=> (opcionalmente calificado con <=>) en el encabezado y una definición única en un archivo C es generalmente el mejor camino a seguir.

Me gustaría ver más contexto para su pregunta. El tipo de valor es crítica, pero lo han dejado fuera. El significado de la palabra clave const en C es muy sutil; por ejemplo     const char * p; no significa que el puntero P es una constante; puede escribir p todo lo que quiera. Lo que no se puede escribir es la memoria que p apunta a, y esto se mantiene fiel incluso cuando cambia el valor de p. Este es el único caso que realmente haya entendido; en general, el significado de la colocación sutil de const se me escapa. Pero este caso especial es extremadamente útil para los parámetros Función: porque se extrae una promesa de la función que la memoria apunta el argumento de que no se mutó.

Hay otro caso especial todo el mundo debe saber: los números enteros. Casi siempre, constantes, enteros nombradas deben definirse en un archivo .h como enumeración literales . tipos de enumeración no sólo le permiten a las constantes relacionadas con agrupar de una manera natural, pero también le permiten a los nombres de esas constantes para ser visto en el depurador, lo cual es una gran ventaja.

He escrito decenas de miles de líneas de C; probablemente cientos si trato de seguir hacia abajo. (Wc ~ / src / c / *. C dice de 85 mil, pero se genera algo de eso, y por supuesto hay una gran cantidad de código C que acechan en otros lugares). Aparte de los dos casos aproximadamente, nunca he encontrado mucho uso para const. Yo estaría encantado de aprender un nuevo ejemplo útil.

Te puedo dar una respuesta indirecta. En C ++ (en oposición a C) const implica static. Eso es decir, en C ++ static const es lo mismo que <=>. Así que te dice cómo ese cuerpo de estándares de C ++ se siente sobre el tema es decir, todos los <=> s deben ser estáticos.

autoconf para el medio ambiente: Siempre se puede definir constantes en el archivo de configuración también. AC_DEFINE () Creo que es la macro para definir a través de toda la construcción.

Para responder a la esencia de su pregunta:
En general, usted no que desee definir una variable estática en un fichero de cabecera.
Esto causaría que tener variables duplicadas en cada unidad de traducción (archivos C) que incluyen la cabecera.

variables en un encabezado realmente deberían ser declarados externo, ya que es la visibilidad implícita. Ver esta pregunta para una buena explicación.

En realidad, la situación podría no ser tan grave, como el compilador probablemente convertir un tipo const a un valor literal. Sin embargo, puede que no desee que confiar en que el comportamiento, especialmente si optimizaciones están apagados.

En C ++, siempre debe utilizar

const int SOME_CONST = 17;

para las constantes y nunca

#define SOME_CONST 17

define casi siempre volver y morder más tarde. Consts están en la lengua, y son fuertemente tipados, por lo que no tendrán errores extraños debido a algún tipo de interacción oculta. Yo pondría la const en el archivo de cabecera apropiado. Mientras que es #pragma una vez (o #ifndef x / x #define / #endif), no se conseguirá nunca ningún errores de compilación.

En la vainilla C, es posible que tenga problemas de compatibilidad en el que debe utilizar #defines.

Si usted desea poner en línea el valor de sus funciones debe utilizar #define MY_MAGIC_NUMBER 0x12345678
Incluso un static const unsigned MY_MAGIC_NUMBER = 0x12345678 hará un valor de recuperar de una dirección.La penalización de rendimiento realmente no importa a menos que el valor de un lote en bucles.
Yo sólo uso const para los argumentos de la función.

Hubo algunos comentarios y abajo votos sobre esta respuesta, he probado mi suposición y ver el ensamblado generado y esta respuesta es incorrecta.Básicamente #define y const dará el mismo resultado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top