Me pregunto por qué este tipo de código puede obtener el tamaño de la matriz de prueba. No estoy familiarizado con la gramática en la plantilla. Tal vez alguien podría explicar el significado del código a continuación template<typename,size_t>
. Además, también se prefiere un enlace de referencia.
#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
void InitDynCalls()
{
char test[20];
size_t n = dimof(test);
printf("%d", n);
}
c++
visual-c++
Demonio de las sombras
fuente
fuente
std::array
ostd::vector
...Respuestas:
Esto es realmente difícil de explicar, pero lo intentaré ...
En primer lugar,
dimof
le indica la dimensión o el número de elementos en una matriz. (Creo que "dimensión" es la terminología preferida en los entornos de programación de Windows).Esto es necesario porque
C++
yC
no le brinda una forma nativa de determinar el tamaño de una matriz.A menudo, las personas suponen
sizeof(myArray)
que funcionará, pero eso realmente le dará el tamaño en la memoria, en lugar de la cantidad de elementos. ¡Cada elemento probablemente toma más de 1 byte de memoria!A continuación, podrían intentarlo
sizeof(myArray) / sizeof(myArray[0])
. Esto daría el tamaño en memoria de la matriz, dividido por el tamaño del primer elemento. Está bien, y se usa ampliamente en elC
código. El principal problema con esto es que parecerá funcionar si pasa un puntero en lugar de una matriz. El tamaño de un puntero en la memoria generalmente será de 4 u 8 bytes, aunque lo que señala podría ser una matriz de miles de elementos.Entonces, lo siguiente que debe probar
C++
es usar plantillas para forzar algo que solo funcione para matrices, y dará un error de compilación en un puntero. Se parece a esto:La plantilla solo funcionará con una matriz. Deducirá el tipo (no es realmente necesario, pero tiene que estar allí para que la plantilla funcione) y el tamaño de la matriz, luego devuelve el tamaño. La forma en que se escribe la plantilla no puede funcionar con un puntero.
Por lo general, puede detenerse aquí, y esto está en la biblioteca estándar de C ++ como
std::size
.Advertencia: aquí abajo se mete en territorio peludo de lenguaje-abogado.
Esto es bastante bueno, pero aún falla en un caso oscuro:
Tenga en cuenta que la matriz
x
se declara , pero no se define . Para llamar a una función (es decirArraySize
) con ella, sex
debe definir .No puedes vincular esto.
El código que tiene en la pregunta es una forma de evitarlo. En lugar de llamar realmente a una función, declaramos una función que devuelve un objeto del tamaño exacto . Luego usamos el
sizeof
truco en eso.Se ve igual que llamamos a la función, pero
sizeof
es puramente una construcción en tiempo de compilación, por lo que la función nunca en realidad se llama.Tenga en cuenta que en realidad no puede devolver una matriz de una función, pero puede devolver una referencia a una matriz.
Entonces
DimofSizeHelper(myArray)
es una expresión cuyo tipo es una matriz enN
char
s. La expresión en realidad no tiene que ser ejecutable, pero tiene sentido en tiempo de compilación.Por
sizeof(DimofSizeHelper(myArray))
lo tanto, le dirá el tamaño en tiempo de compilación de lo que obtendría si realmente llamara a la función. Aunque en realidad no lo llamamos.No te preocupes si ese último bloque no tiene sentido. Es un truco extraño evitar un caso extraño. Es por eso que no escribe este tipo de código usted mismo, y deja que los implementadores de la biblioteca se preocupen por este tipo de tonterías.
fuente
DimofSizeHelper
es una función de plantilla que toma unT(&)[N]
parámetro, es decir, una referencia a una matriz C de N elementos de tipoT
y devuelvechar (&)[N]
una referencia aka a una matriz de N caracteres. En C ++, un carácter es un byte disfrazado ysizeof(char)
está garantizado1
por el estándar.n
se le asigna el tamaño del tipo de retorno deDimofSizeHelper
, que essizeof(char[N])
cuál esN
.Esto es un poco complicado
e innecesario. La forma habitual de hacerlo era:Desde C ++ 17 esto también es innecesario, ya que tenemos
std::size
quién hace esto, pero de una manera más genérica, pudiendo obtener el tamaño de cualquier contenedor de estilo stl.Como señaló BoBTFish, es necesario para un caso de borde.
fuente
std::extent
desde C ++ 11 que es tiempo de compilación.