Primeiro, aqui está um código:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Existe uma maneira de descobrir o tamanho da matriz que ptr
está apontando (em vez de apenas fornecer seu tamanho, que é de quatro bytes em um sistema de 32 bits)?
Respostas:
Não, você não pode. O compilador não sabe para onde o ponteiro está apontando. Existem truques, como finalizar a matriz com um valor fora da banda conhecido e contar o tamanho até esse valor, mas isso não está sendo usado
sizeof()
.Outro truque é o mencionado por Zan , que é esconder o tamanho em algum lugar. Por exemplo, se você estiver alocando dinamicamente a matriz, aloque um bloco um int maior que o necessário, armazene o tamanho no primeiro int e retorne
ptr+1
como ponteiro para o array. Quando você precisar do tamanho, diminua o ponteiro e espreite o valor escondido. Lembre-se de liberar todo o bloco começando do início, e não apenas o array.fonte
A resposta é não."
O que os programadores C fazem é armazenar o tamanho da matriz em algum lugar. Pode fazer parte de uma estrutura ou o programador pode enganar um pouco
malloc()
mais de memória do que o solicitado para armazenar um valor de comprimento antes do início da matriz.fonte
Para matrizes dinâmicas ( malloc ou C ++ novo ), é necessário armazenar o tamanho da matriz como mencionado por outros ou talvez criar uma estrutura de gerenciador de matriz que lide com adicionar, remover, contar etc. Infelizmente, C não faz isso tão bem quanto C ++, já que você basicamente precisa criá-lo para cada tipo de matriz diferente que você está armazenando, o que é complicado se você tiver vários tipos de matrizes que precisa gerenciar.
Para matrizes estáticas, como a do seu exemplo, existe uma macro comum usada para obter o tamanho, mas isso não é recomendado , pois não verifica se o parâmetro é realmente uma matriz estática. A macro é usada no código real, por exemplo, nos cabeçalhos do kernel do Linux, embora possa ser um pouco diferente da abaixo:
Você pode pesquisar no Google por motivos de desconfiança em relação a macros como essa. Seja cuidadoso.
Se possível, o stdlib do C ++, como vetor, é muito mais seguro e fácil de usar.
fonte
ARRAY_SIZE
macro sempre funciona se seu argumento for uma matriz (ou seja, expressão do tipo de matriz). Para a chamada "matriz dinâmica", você nunca obtém uma "matriz" real (expressão do tipo de matriz). (Obviamente, você não pode, pois os tipos de matriz incluem seu tamanho em tempo de compilação.) Você apenas obtém um ponteiro para o primeiro elemento. Sua objeção "não verifica se o parâmetro é realmente uma matriz estática" não é realmente válida, pois são diferentes porque uma é uma matriz e a outra não.Existe uma solução limpa com modelos C ++, sem usar sizeof () . A seguinte função getSize () retorna o tamanho de qualquer matriz estática:
Aqui está um exemplo com uma estrutura foo_t :
Resultado:
fonte
T (&)[SIZE]
. Você pode explicar o que isso significa? Você também pode mencionar constexpr neste contexto.SIZE
como um argumento, é um parâmetro de modelo que possui para já ser conhecida pela definição de função).Para este exemplo específico, sim, existe, se você usar typedefs (veja abaixo). Obviamente, se você fizer dessa maneira, poderá usar SIZEOF_DAYS, pois sabe para onde o ponteiro está apontando.
Se você tiver um ponteiro (void *), retornado por malloc () ou algo semelhante, não, não há como determinar para qual estrutura de dados o ponteiro está apontando e, portanto, não há como determinar seu tamanho.
Resultado:
fonte
Como todas as respostas corretas declararam, você não pode obter essas informações apenas com o valor do ponteiro deteriorado da matriz. Se o ponteiro deteriorado é o argumento recebido pela função, o tamanho da matriz de origem deve ser fornecido de outra maneira para que a função conheça esse tamanho.
Aqui está uma sugestão diferente do que foi fornecido até agora, que funcionará: passe um ponteiro para a matriz. Essa sugestão é semelhante às sugestões de estilo C ++, exceto que C não suporta modelos ou referências:
Mas, essa sugestão é meio boba para o seu problema, já que a função é definida para saber exatamente o tamanho da matriz que é passada (portanto, há pouca necessidade de usar sizeof na matriz). O que ele faz, no entanto, é oferecer algum tipo de segurança. Isso o proibirá de transmitir uma matriz de tamanho indesejado.
Se a função deve poder operar em qualquer tamanho de matriz, você precisará fornecer o tamanho da função como informações adicionais.
fonte
Não há solução mágica. C não é uma linguagem reflexiva. Os objetos não sabem automaticamente o que são.
Mas você tem muitas opções:
fonte
Minha solução para esse problema é salvar o comprimento da matriz em uma matriz de estrutura como uma meta-informação sobre a matriz.
Mas você precisa se preocupar em definir o tamanho certo da matriz que deseja armazenar, porque não há como verificar esse tamanho, como explicaram massivamente nossos amigos.
fonte
Você pode fazer algo assim:
fonte
Não, você não pode
sizeof(ptr)
encontrar o tamanho da matriz queptr
está apontando.Embora alocar memória extra (mais do que o tamanho da matriz) seja útil se você deseja armazenar o comprimento em espaço extra.
fonte
Tamanho dos dias [] é 20, que não possui elementos * tamanho do seu tipo de dados. Enquanto o tamanho do ponteiro é 4, não importa para o que ele está apontando. Porque um ponteiro aponta para outro elemento armazenando seu endereço.
fonte
array_size está passando para a variável size :
O uso é:
fonte
Nas strings existe um
'\0'
caractere no final, então o comprimento da string pode ser obtido usando funções comostrlen
. O problema com uma matriz inteira, por exemplo, é que você não pode usar nenhum valor como valor final; portanto, uma solução possível é endereçar a matriz e usar comoNULL
ponteiro o valor final .fonte
NULL
é provavelmente a alternativa menos eficiente que se pode imaginar para armazenarsize
diretamente um item separado . Especialmente se você realmente usa essa camada extra de indireção o tempo todo.