He escrito el siguiente código en C
int main(){ int a = {1, 2, 3}; }Parece que la variable asignada, en este caso a, siempre toma el valor del primer elemento del arreglo. Ahora me pregunto si los otros elementos de la matriz se descartan o se escriben en la memoria después de a, lo que provoca un desbordamiento del búfer.
Esta declaración
int a = {1, 2, 3};es semánticamente inválida (rompe la regla semántica a la que se hace referencia a continuación). Un objeto escalar no puede ser inicializado por una lista de inicializadores entre llaves con más de un inicializador.
Del Estándar C (6.7.9 Inicialización)
11 El inicializador de un escalar será una sola expresión, opcionalmente encerrada entre llaves. El valor inicial del objeto es el de la expresión (después de la conversión); se aplican las mismas restricciones de tipo y conversiones que para la asignación simple, tomando el tipo del escalar como la versión no calificada de su tipo declarado.
Es decir, la coma en la lista de inicializadores entre llaves se considera como un separador de inicializadores y para un objeto escalar solo se permite una sola expresión.
Cuando hay más de un inicializador presente, el compilador asume que el objeto inicializado es un agregado.
Para declarar una matriz necesitas escribir
int a[] = {1, 2, 3};o
int a[N] = {1, 2, 3}; donde N es un valor entero igual o mayor que 3.
int a = {1, 2, 3}; no es un código C válido.
Es la llamada violación de restricción en el estándar C, después de lo cual se requiere que un compilador emita un mensaje de diagnóstico:
C17 6.7.9/2:
Restricciones
Ningún inicializador intentará proporcionar un valor para un objeto que no esté contenido dentro de la entidad que se está inicializando.
Sin embargo, no es un error de sintaxis, en realidad podemos escribir cosas extrañas como int a = {1}; con un único inicializador entre llaves. Sin embargo, el resultado, sin importar el motivo del error, es el mismo: los compiladores deben emitir mensajes de diagnóstico para todas las violaciones de restricciones y sintaxis.
Para evitar perder el tiempo solucionando problemas de código C inválido como este, estudie ¿Qué opciones de compilador se recomiendan para los principiantes que aprenden C?
En cuanto a lo que hacen los compiladores como gcc y clang cuando se enfrentan a un código no estándar, parecen simplemente descartar los inicializadores superfluos. Si compilo este código con gcc/clang para x86 e ignoro el mensaje de diagnóstico:
int foo (void) { int a = {1, 2, 3}; return a; }El ensamblado x86 resultante es
mov eax, 1 retQue cuando se traduce de nuevo a C es 100% equivalente a
int foo (void) { return 1; }Sin embargo, es importante comprender que esta es una extensión de compilador no estándar y que no tiene un comportamiento garantizado o portátil.
int main(void) { int a[3] = {1, 2, 3}; printf("%d\n", a[0]); return(0); } Output : 1