paulo1205
(usa Ubuntu)
Enviado em 25/07/2020 - 11:21h
Bom dia, prezado.
Note que
sizeof não é uma função, mas sim um operador.
Se
A tiver sido declarado como um
array com elementos de um tipo qualquer, a forma usual de calcular o número de elementos é fazer o seguinte.
sizeof A/sizeof A[0]
Como o C não permite passar
arrays como parâmetros de função, dado que eles decaem para ponteiros automaticamente (exceto justamente quando usados como operandos de
sizeof ou de
& ), você não pode fazer uma função que calcule o número de elementos. Se tentar fazê-lo da forma usual (i.e. recebendo um ponteiro), você vai acabar calculando quantas vezes o tamanho do ponteiro é maior do que o tamanho do elemento, o que pode inclusive provocar tamanho zero.
/*** ATENÇÃO: ESTAS IMPLEMENTAÇÕES ESTÃO ERRADAS. NÃO USE! ***/
#include <stdio.h>
struct big_struct {
uint64_t many_elements[10000]; // 10 mil elementos com de 8 bytes, totalizando 80 mil bytes.
};
struct big_struct big_array[10000]; // 10 mil elementos de 80 mil bytes, com tamanho total de 800 milhões de bytes.
size_t bad_big_struct_array_size(struct big_struct *p){
return sizeof pi/sizeof *pi; // Certamente vai retornar 0, porque sizeof de ponteiro deve ser 4 ou 8 bytes, que, divididos por 80 mil, dá zero.
}
int main(){
printf("%zu\n", szieof big_struct_array/sizeof big_struct_array[0]); // Vai imprimir 10000. OK.
printf("%zu\n", bad_big_struct_array_size(big_struct_array)); // Vai imprimir 0. Ruim, mas “correto”, de acordo com as regras da linguagem.
}
A alternativa para fazer em C é através de macros. Como as macros expandem o código dentro do local onde elas são usadas, a construção “
sizeof x/sizeof x[0] ” pode aparecer como consequência da expansão
in loco , desde que de tomem certos cuidados.
// Os parênteses são necessários para evitar alguns problemas quando “x” tem formas compostas, como “a+n” ou “(a, b)”.
#define better_array_size(x) (sizeof (x)/sizeof (x)[0])
Note que o exemplo acima não evita certos erros, tais como chamar a macro com um ponteiro, em vez de com um
array , dá margem a comportamentos estranhos com efeitos colaterais ao expandir
x duas vezes, e é sujeita a erros de compilação relativamente difíceis de depurar quando o argumento não é nem um
array nem um ponteiro.
Se você estiver usando C++, o uso de
templates ajuda a eliminar erros que ocorrem com macros.
template <typename T, size_t N> constexpr size_t array_size(const T(&)[N]){ return N; }
Essa função tem todas as vantagens da forma anterior com macros, mas não tem os defeitos de poder ser chamada com ponteiro em vez de
array , não está sujeita a efeitos colaterais, já que não há expansão de macro, nem tem problema com expressões compostas.
... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)