2012-04-10 11 views
7

Acabo de tener el compilador C/C++ de Apple inicializar un flotador a un valor distinto de cero (aproximadamente "-0.1").¿A qué se inicializan por defecto los tipos primitivos en C?

Eso fue una gran sorpresa, y solo sucedió de vez en cuando (pero 100% repetible, si ejecutó previamente la misma función llamadas/argumentos de antemano). Tomó mucho tiempo rastrear (usando aserciones).

Pensé que las carrozas no se inicializaron. Google sugiere que estaba pensando en C++ (que, por supuesto, es mucho más preciso sobre este tema - c.f. SO: What are primitive types default-initialized to in C++?).

Pero tal vez la excusa de Apple aquí es que su compilador se estaba ejecutando en modo C ... entonces: ¿qué pasa con C? ¿Qué debería pasar y (más importante) qué es típico?

(por supuesto yo, hubiera inicializado manualmente - Yo normalmente - pero en éste caso no he logrado yo no esperaba que hiciera saltar, sin embargo.!)

(Google está resultando peor que inútil para cualquier discusión de este -. su búsqueda actual se niega a mostrar "C" sin "C++" Keeps decidir que soy demasiado estúpida, e ignorando incluso mi entrada, incluso cuando se ejecuta en modo avanzado)


Aquí está el real ejemplo de fuente donde sucedió. Al principio pensé que podría haber un problema con las definiciones de MAX y ABS (¿tal vez MAX (ABS, ABS) no siempre hace lo que cabría esperar?) ... pero cavando con aserciones y depuraciones, finalmente encontré que faltaba inicialización - flotador que se iba a init'd valor distinto de cero muy ocasionalmente):

float crossedVectorX = ... // generates a float 
float crossedVectorY = ... // generates a float 

float infitesimal; // no manual init 
float smallPositiveFloat = 2.0/MAX(ABS(crossedVectorX), ABS(crossedVectorY)); 

// NB: confirmed with debugger + assertions that smallPositiveFloat was always positive 

infitesimal += smallPositiveFloat; 

NSAssert(infitesimal >= 0.0, @"This is sometimes NOT TRUE"); 
+0

Depende de dónde se produzca esa "inicialización", es posible que no se inicialice en absoluto. – Mat

+0

Agregué copiar/pegar de la fuente donde vi el problema. Me pareció que debería haber sido iniciado? – Adam

+1

+1 por hacer una pregunta que a todos les conviene saber la respuesta. – borrrden

Respuesta

17

Sólo los objetos con una duración de almacenamiento estático se inicializa a 0 si no hay un inicializador explícito.

#include <stdio.h> 

float f;   // initialized to 0, file scope variables have static storage 
static float g; // initialized to 0 

int main(void) 
{ 
    float h; // not initialized to 0, automatic storage duration 
    static float i; // initialized to 0 

    return 0; 
} 

Los objetos con una duración de almacenamiento automático (como h en el ejemplo anterior) que no se inicializa explícitamente tienen un valor indeterminado. Leer su valor es un comportamiento indefinido.

EDIT: para la mayor abundamiento, ya que los objetos C11 con una duración de almacenamiento de hilo también se inicializan a 0 si no hay un inicializador explícito.

+2

Gracias. Aquí hay muchas buenas respuestas, pero en mi humilde opinión, decirlo así hace que sea más fácil de entender de un vistazo. – Adam

+0

De acuerdo, me gusta el formato de esta respuesta. –

0

No creo que ninguno de los estándares para C defina los valores iniciales para las variables en general. Esto estaría de acuerdo con la filosofía general de y el dominio de aplicación para C - programación para adultos que pueden, un día, tener razones para querer que su compilador no inicialice una variable para ellos y que sepan que es su responsabilidad inicializar sus propias variables.

+2

Como se mencionó anteriormente, las variables de archivo y globales se inicializan a cero de forma predeterminada. – Kevin

5

Variable estática se inicializa a cero, pero supongo que está hablando una variable local (es decir, pila, o automático) - estos no se inicializan para usted, pero conseguir cualquier valor está en que la memoria de la pila.

9

La parte relevante de la norma es §6.7.9 párrafo 10:

Si un objeto que tiene una duración de almacenamiento automático no se inicializa de forma explícita, su valor es indeterminado.

Si la variable tenía hilo o la duración de almacenamiento estático en su lugar, a continuación, la siguiente parte del párrafo entraría en vigor:

Si un objeto que tiene una duración de almacenamiento estático o hilo no se ha inicializado de forma explícita, a continuación, :

- si tiene un tipo de puntero, se inicializa a un puntero nulo;

- si tiene tipo aritmético, se inicializa a cero (positivo o sin signo);

...

yo también en cuenta que debe activar las advertencias de su compilador (en concreto la advertencia para las variables sin inicializar), como que debería haber identificado el problema de forma inmediata.

1

tuve que sacar mi K & R para esta respuesta:

En ausencia de inicialización explícita, las variables externas y estáticas están garantizados para ser inicializado a cero; las variables automáticas y de registro tienen valores iniciales indefinidos (es decir, basura).

Cuestiones relacionadas