Gostaria de saber por que esse tipo de código pode obter o tamanho da matriz de teste? Não estou familiarizado com a gramática no modelo. Talvez alguém possa explicar o significado do código abaixo template<typename,size_t>
. Além disso, um link de referência também é preferido.
#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++
Demônio das Sombras
fonte
fonte
std::array
oustd::vector
....Respostas:
Isso é realmente difícil de explicar, mas vou tentar ...
Em primeiro lugar,
dimof
informa a dimensão ou o número de elementos em uma matriz. (Eu acredito que "dimensão" é a terminologia preferida nos ambientes de programação do Windows).Isso é necessário porque
C++
eC
não fornece uma maneira nativa de determinar o tamanho de uma matriz.Muitas vezes, as pessoas assumem
sizeof(myArray)
que funcionará, mas isso realmente fornecerá o tamanho da memória, e não o número de elementos. Cada elemento provavelmente leva mais de 1 byte de memória!Em seguida, eles podem tentar
sizeof(myArray) / sizeof(myArray[0])
. Isso daria o tamanho na memória da matriz, dividido pelo tamanho do primeiro elemento. Está tudo bem, e amplamente usado emC
código. O principal problema disso é que ele parecerá funcionar se você passar um ponteiro em vez de uma matriz. O tamanho de um ponteiro na memória geralmente será de 4 ou 8 bytes, mesmo que o item para o qual ele aponta possa ser uma matriz de 1000s de elementos.Portanto, a próxima coisa a experimentar
C++
é usar modelos para forçar algo que só funciona para matrizes e fornecerá um erro de compilador em um ponteiro. Se parece com isso:O modelo funcionará apenas com uma matriz. Deduzirá o tipo (não é realmente necessário, mas precisa estar lá para que o modelo funcione) e o tamanho da matriz e, em seguida, retornará o tamanho. A maneira como o modelo é escrito não pode funcionar com um ponteiro.
Geralmente você pode parar por aqui, e isso está no C ++ Standard Libary como
std::size
.Atenção: aqui embaixo entra em território peludo-advogado de línguas.
Isso é bem legal, mas ainda falha em um caso de borda obscuro:
Observe que a matriz
x
é declarada , mas não definida . Para chamar uma função (ou sejaArraySize
) com ela,x
deve ser definido .Você não pode vincular isso.
O código que você tem na pergunta é uma maneira de contornar isso. Em vez de realmente chamar uma função, declaramos uma função que retorna um objeto exatamente do tamanho certo . Então nós usamos o
sizeof
truque nisso.Ele olha como nós chamamos a função, mas
sizeof
é puramente uma construção tempo de compilação, assim que a função nunca realmente é chamado.Observe que você não pode realmente retornar uma matriz de uma função, mas pode retornar uma referência a uma matriz.
Então
DimofSizeHelper(myArray)
é uma expressão cujo tipo é uma matriz emN
char
s. A expressão não precisa ser executável, mas faz sentido em tempo de compilação.Portanto
sizeof(DimofSizeHelper(myArray))
, informará o tamanho em tempo de compilação do que você obteria se realmente chamasse a função. Mesmo que na verdade não chamemos isso.Não se preocupe se esse último bloco não fizer sentido. É um truque bizarro contornar um caso estranho. É por isso que você não escreve esse tipo de código e deixa os implementadores de bibliotecas se preocupar com esse tipo de bobagem.
fonte
DimofSizeHelper
é uma função de modelo que usa umT(&)[N]
parâmetro - também conhecido como referência a um array C de N elementos do tipoT
e retorna umchar (&)[N]
conhecido como referência a um array de N caracteres. Em C ++, um caractere é byte disfarçado esizeof(char)
é garantido1
pelo padrão.n
é atribuído o tamanho do tipo de retorno deDimofSizeHelper
qual ésizeof(char[N])
qual éN
.Isso é um pouco complicado
e desnecessário. A maneira usual de fazer isso era:Desde o C ++ 17, isso também é desnecessário, pois temos o
std::size
que faz isso, mas de uma maneira mais genérica, podendo obter o tamanho de qualquer contêiner no estilo stl.Como apontado pelo BoBTFish, é necessário um caso de borda.
fonte
std::extent
desde C ++ 11 que é tempo de compilação.