Quiero declarar un arreglo constante al que se puede acceder desde múltiples archivos C y cuyo contenido puede ser insertado por el compilador, sin duplicar la memoria en varias unidades de compilación. El rendimiento es crítico en mi aplicación.Arreglo constante C invisible sin duplicación de memoria
Anexo 1:
header.h:
static const int arr[2] = { 1, 2 };
file1.c:
#include "header.h"
void file1() { printf("%d\n", arr[0]); }
file2.c:
#include "header.h"
int file2() { for (int i = 0; i < 2; i++) printf("%d\n", arr[i]); }
En ese caso, el compilador puede reemplazar por arr[0]
1
en archivo1. Sin embargo, dado que arr
está declarado static const
, su memoria está duplicada en ambos archivos C. AFAIK el estándar C requiere que las direcciones de matriz sean diferentes en ambos archivos. Lo he verificado en Linux imprimiendo las direcciones. No se produce consolidación de vinculador incluso con -fmerge-all-constants
en gcc.
Anexo 2:
header.h:
extern const int arr[2];
file1.c:
#include "header.h"
void file1() { printf("%d\n", arr[0]); }
file2.c:
#include "header.h"
const int arr[2] = { 1, 2 };
int file2() { for (int i = 0; i < 2; i++) printf("%d\n", arr[i]); }
En ese caso, no se produce la duplicación de memoria, pero no arr[0]
se colocarán en línea.
Considero que el alcance de visibilidad definido por el estándar C es defectuoso. Como tal, una solución de trabajo bajo Linux/gcc que viola el estándar C es aceptable para mí.
En realidad, 'file2' también permite inlining la matriz. 'gcc -O9' desenrolla el ciclo y empuja directamente los dos valores. – aschepler
@aschepler: Sí. En mi sistema, con -O2, el compilador deja de alinearse una vez que establezco tres o más elementos en la matriz. –