NK-célula
Golpeé algo de c código en el núcleo de Linux:
static struct ctl_table ip_ct_sysctl_table[] = {
{
.procname = "ip_conntrack_max",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
// ...
{
.procname = "ip_conntrack_log_invalid",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &log_invalid_proto_min,
.extra2 = &log_invalid_proto_max,
},
{ }
};
Aquí una matriz de estructuras termina con { }
. ¿Con qué propósito se agregó?
Por cierto, un poco más arriba de este código hay otro matriz de estructuraspero sin llaves vacías al final.
¿Cuándo debo usar llaves vacías al final de una matriz de estructuras?
dfrib
Este cambio en particular fue parte de la sysctl net: elimina el código sysctl binario no utilizado cometer por Eric W. Biederman, cambiando la inicialización del último elemento de la ip_ct_sysctl_table
matriz de {0}
a {}
(y realiza cambios similares a muchas otras inicializaciones de matrices).
los {0}
Sin embargo, el patrón parece haber existido por mucho más tiempo, y ambos {0}
o {}
la inicialización del elemento final se denomina comúnmente (en el código fuente de Linux) explícitamente como Terminating entry
, por lo que es probable que haya un patrón presente para permitir el consumo de estas matrices sin conocer sus longitudes, finalizando el consumo al llegar a la entrada final inicializada en cero. Por ejemplo, para las matrices similares en sound/aoa/fabrics/snd-aoa-fabric-layout.c
la intención de la inicialización cero incluso se menciona explícitamente en un comentario, por ejemplo:
static struct codec_connection toonie_connections[] = { { .connected = CC_SPEAKERS | CC_HEADPHONE, .codec_bit = 0, }, {} /* terminate array by .connected == 0 */ };
-
Sería interesante conocer su justificación para abandonar el estándar C en favor de una extensión GCC que sea 100 % equivalente en términos de funcionalidad. Todo lo que hace es evitar que el código se compile en los compiladores estándar de C. Es decir, supuestamente 100% equivalente porque gcc no parece documentar esta característica… Esto es no una matriz de longitud cero, es una lista de inicializadores vacía.
– Lundin
2 de marzo de 2020 a las 15:32
-
@Lundin no lo haría
int arr[] = {}
(dado que estamos usando la extensión de inicializador vacío GNU) da como resultado una matriz vacía; es decir, el tamaño dearr
siendo0
?– dfrib
2 de marzo de 2020 a las 16:02
-
@Lundin: Sin embargo, la página cppreference está en conflicto con la redacción de ISO/IEC 9899:2011, que lo permite (§6.7.9 (21)). No hay inicializadores, sin duda, “menos” que los miembros del agregado. Entonces esa no es una extensión de compilador queer, sino C.
– Damon
3 de marzo de 2020 a las 12:19
-
@Damon No es C válido y es bien conocido… compilar con gcc -pedantic-errors. Para comprender por qué, debe leer la sintaxis real de una lista de inicializadores, en la parte superior de 6.7.9. Debe haber al menos un inicializador. Explicado aquí: stackoverflow.com/questions/17589533/…. Específicamente
{ initializer-list }
luego la lista de inicializadores:designation(opt) initializer
oinitializer-list , designation(opt) initializer
– Lundin
3 de marzo de 2020 a las 12:43
-
@Lundin En este caso específico, ni idea. Pero las extensiones gcc se usan mucho en el kernel de Linux.
– quemador de bobs
3 de marzo de 2020 a las 13:31
Probablemente esté familiarizado con las cadenas terminadas en cero. ctl_table ip_ct_sysctl_table[]
es una matriz terminada en cero, es decir, la última entrada de la matriz tiene todos los miembros cero.
-
Entonces, al recorrer la matriz, sabe que ha llegado al final cuando, por ejemplo,
procname
es nulo, omaxlen
es cero–Paul Ogilvie
2 de marzo de 2020 a las 13:24
-
@PaulOgilvie: Bueno, el ejemplo está incompleto.
procname
podría ser unchar[100]
en cuyo caso es""
, no nulo. Pero por lo demás si.– MSalters
2 de marzo de 2020 a las 13:57
¿Cuál es la necesidad de llaves vacías ‘{ }’ al final de la matriz de estructuras?
Para ser claros: las “llaves vacías ‘{ }’ al final de la matriz de estructuras” no son necesario para satisfacer los requisitos de sintaxis de C.
¿Cuándo debo usar llaves vacías al final de una matriz de estructuras?
Cuando el código quiere un valor centinela.
Lo es a veces útil para que el programa tenga un elemento de matriz final de todos ceros, ciertamente para detectar el final. los necesitar proviene del uso de matriz de la aplicación ctl_table ip_ct_sysctl_table[]
no de una necesidad de lenguaje C.
Jabberwocky
Es un elemento inicializado en cero al final de la matriz para aumentar la cantidad de elementos de la matriz en uno.
Considere esta pequeña demostración:
#include <stdio.h>
struct Test
{
int x;
int y;
} arr[] =
{
{1,2},
{3,4},
// {}
};
int main(void) {
printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
return 0;
}
el tamaño de la arr
la matriz cambiará si descomentas el {}
al final de la lista de inicialización de la matriz.
Salidas:
Con // {}
(el arreglo tiene 2 elementos)
2
Con {}
(el arreglo tiene 3 elementos)
3
Explicación adicional:
los ip_ct_sysctl_table
array solo se usa en un lugar, que es aquí:
in->ctl_table = kmemdup(ip_ct_sysctl_table,
sizeof(ip_ct_sysctl_table),
GFP_KERNEL);
El extra {}
aumenta el tamaño total ip_ct_sysctl_table
.
Hmm, ¿qué pasa si se agrega para señalar el final de la matriz como 0 señala el final de la cadena? Solo adivinando.
– Eraklon
2 de marzo de 2020 a las 13:07
Esta es una extensión GCC no estándar. Y como tal, es muy probable que venga con poca o ninguna documentación… Acabo de leer todos los documentos y no puedo encontrar nada sobre listas de inicializadores de estructuras vacías. Sin embargo, compila, a menos que fuerce ISO estricto con
-pedantic
.– Lundin
2 de marzo de 2020 a las 13:35
De todos modos, es un valor “centinela”, un elemento con todo configurado en cero/NULL para marcar el final de la matriz.
– Lundin
2 de marzo de 2020 a las 13:40
Los centinelas también son comunes en Módulos de extensión de CPython.
– MaxPowers
2 de marzo de 2020 a las 22:06