Esto es principalmente una continuación de ¿Deberían coincidir la definición y la declaración?
¿Es legal en C tener (por ejemplo) int a[10]; en una unidad de compilación y extern int a[4]; en otro?
(Puede encontrar un ejemplo de trabajo en mi respuesta a la pregunta referida)
Descargos de responsabilidad:
Incluso si diferentes comentarios en la publicación a la que se hace referencia lo detectaron como UB, no pude encontrar ninguna referencia autorizada para ello. Entonces, diría que no hay UB aquí y que la segunda unidad de compilación tendrá acceso al comienzo de la matriz, pero realmente me gustaría una confirmación, o en su lugar, una referencia sobre por qué es UB.
Es un comportamiento indefinido.
La sección 6.2.7.2 de C99 establece:
Todas las declaraciones que se refieran a un mismo objeto o función deberán tener tipo compatible; de lo contrario, el comportamiento no está definido.
NOTA : Como se menciona en los comentarios a continuación, la parte importante aquí es [...] que se refieren al mismo objeto [...] , que se define con más detalle en 6.2.2:
En el conjunto de unidades de traducción y bibliotecas que constituye un programa completo, cada declaración de un identificador particular con enlace externo denota el mismo objeto o función.
Acerca de las reglas de compatibilidad de tipos para tipos de matrices, la sección 6.7.5.2.4 de C99 aclara lo que significa que dos tipos de matrices sean compatibles:
Para que dos tipos de matrices sean compatibles, ambos deben tener tipos de elementos compatibles, y si ambos especificadores de tamaño están presentes y son expresiones constantes enteras, ambos especificadores de tamaño deben tener el mismo valor constante . Si los dos tipos de matrices se usan en un contexto que requiere que sean compatibles, es un comportamiento indefinido si los dos especificadores de tamaño se evalúan como valores diferentes.
(Énfasis mío)
En el mundo real, siempre que se adhiera a matrices 1D, probablemente sea inofensivo, porque no hay verificación de límites y la dirección del primer elemento sigue siendo la misma independientemente del especificador de tamaño, pero tenga en cuenta que el operador sizeof devolverá diferente valores en cada archivo fuente (abriendo una maravillosa oportunidad para escribir código con errores).
Las cosas empiezan a ponerse realmente feas si decide extrapolar este ejemplo y declarar matrices multidimensionales con diferentes tamaños de dimensión, porque el desplazamiento de cada elemento de la matriz ya no coincidirá con las dimensiones reales.
Sí, es legal. El lenguaje lo permite.
En su caso específico, no habrá un comportamiento indefinido ya que la matriz declarada extern es más pequeña que la matriz realmente asignada.
Se puede utilizar en un caso en el que el módulo declarante utilice los elementos de matriz "no publicados" para, por ejemplo, el mantenimiento de sus algoritmos (ocultación de abstracción).