Para determinar o tamanho da sua matriz em bytes, você pode usar o sizeof
operador:
int a[17];size_t n =sizeof(a);
No meu computador, ints têm 4 bytes de comprimento, então n é 68.
Para determinar o número de elementos na matriz, podemos dividir o tamanho total da matriz pelo tamanho do elemento da matriz. Você poderia fazer isso com o tipo, assim:
int a[17];size_t n =sizeof(a)/sizeof(int);
e obtenha a resposta correta (68/4 = 17), mas se o tipo de
aalteração for alterado, você terá um erro desagradável se esquecer de alterar sizeof(int)também.
Portanto, o divisor preferido é sizeof(a[0])ou equivalente sizeof(*a), o tamanho do primeiro elemento da matriz.
int a[17];size_t n =sizeof(a)/sizeof(a[0]);
Outra vantagem é que agora você pode facilmente parametrizar o nome da matriz em uma macro e obter:
#define NELEMS(x)(sizeof(x)/sizeof((x)[0]))int a[17];size_t n = NELEMS(a);
O código gerado será idêntico, pois o compilador conhece o tipo de * int_arr em tempo de compilação (e, portanto, o valor de sizeof (* int_arr)). Será uma constante, e o compilador pode otimizar adequadamente.
Mark Harrison
10
Deve ser o caso de todos os compiladores, pois os resultados de sizeof são definidos como uma constante em tempo de compilação.
Mark Harrison
451
Importante : Não pare de ler aqui, leia a próxima resposta! Isso funciona apenas para matrizes na pilha , por exemplo, se você estiver usando malloc () ou acessando um parâmetro de função, estará sem sorte. Ver abaixo.
Markus
7
Para a programação da API do Windows em C ou C ++, existe o ARRAYSIZEmakro definido em WinNT.h(que é puxado por outros cabeçalhos). Portanto, os usuários do WinAPI não precisam definir seu próprio makro.
Lumi
17
@ Markus funciona para qualquer variável que tenha um tipo de array; isso não precisa estar "na pilha". Por exemplo static int a[20];. Mas seu comentário é útil para leitores que podem não perceber a diferença entre uma matriz e um ponteiro.
MM
808
O sizeofcaminho é o caminho certo se você estiver lidando com matrizes não recebidas como parâmetros. Uma matriz enviada como parâmetro para uma função é tratada como um ponteiro; portanto sizeof, retornará o tamanho do ponteiro, em vez do tamanho da matriz.
Assim, funções internas esse método não funciona. Em vez disso, sempre passe um parâmetro adicional size_t sizeindicando o número de elementos na matriz.
Teste:
#include<stdio.h>#include<stdlib.h>void printSizeOf(int intArray[]);void printLength(int intArray[]);int main(int argc,char* argv[]){intarray[]={0,1,2,3,4,5,6};
printf("sizeof of array: %d\n",(int)sizeof(array));
printSizeOf(array);
printf("Length of array: %d\n",(int)(sizeof(array)/sizeof(array[0])));
printLength(array);}void printSizeOf(int intArray[]){
printf("sizeof of parameter: %d\n",(int)sizeof(intArray));}void printLength(int intArray[]){
printf("Length of parameter: %d\n",(int)(sizeof(intArray)/sizeof(intArray[0])));}
Saída (em um sistema operacional Linux de 64 bits):
sizeof of array:28sizeof of parameter:8Length of array:7Length of parameter:2
Saída (em um sistema operacional Windows de 32 bits):
sizeof of array:28sizeof of parameter:4Length of array:7Length of parameter:1
por que length of parameter:2se apenas um ponteiro para o primeiro elemento da matriz for passado?
Bbvarghe 5/08/2013
16
@Bbvarghe Isso ocorre porque os ponteiros nos sistemas de 64 bits têm 8 bytes (sizeof (intArray)), mas as entradas ainda têm (geralmente) 4 bytes de comprimento (sizeof (intArray [0])).
Elideb
13
@ Pacerier: Não há código correto - a solução usual é passar o comprimento junto com o array como um argumento separado.
precisa saber é o seguinte
10
Espere, então não há como acessar a matriz diretamente de um ponteiro e ver seu tamanho? Novo para C aqui.
Sudo #
7
@ Michael Trouw: você pode usar a sintaxe operador, se é te faz sentir melhor: (sizeof array / sizeof *array).
precisa saber é
134
Vale ressaltar que sizeofisso não ajuda ao lidar com um valor de matriz que se deteriorou para um ponteiro: mesmo que aponte para o início de uma matriz, para o compilador é o mesmo que um ponteiro para um único elemento dessa matriz . Um ponteiro não "lembra" mais nada sobre a matriz que foi usada para inicializá-lo.
int a[10];int* p = a;
assert(sizeof(a)/sizeof(a[0])==10);
assert(sizeof(p)==sizeof(int*));
assert(sizeof(*p)==sizeof(int));
@ Magnus: O padrão define sizeof como produzindo o número de bytes no objeto e esse sizeof (char) é sempre um. O número de bits em um byte é específico da implementação. Editar: seção padrão ANSI C ++ 5.3.3 Sizeof: "O operador sizeof gera o número de bytes na representação do objeto de seu operando. Sizeof [...] (char), sizeof (char assinado) e sizeof (char não assinado) são 1; o resultado do tamanho do aplicado a qualquer outro tipo fundamental é definido pela implementação ".
Skizz
Seção 1.6 O modelo de memória C ++: "A unidade de armazenamento fundamental no modelo de memória C ++ é o byte. Um byte é pelo menos grande o suficiente para conter qualquer membro do conjunto de caracteres de execução básica e é composto por uma sequência contígua de bits, o número dos quais é definido pela implementação ".
Skizz
2
Lembro que o CRAY tinha C com char32 bits. Tudo o que o padrão diz é que valores inteiros de 0 a 127 podem ser representados e seu intervalo é de pelo menos -127 a 127 (o caractere é assinado) ou de 0 a 255 (o caracter não é assinado).
21133 vonbrand
5
Esta é uma excelente resposta. Quero comentar que todas as afirmações acima são avaliadas como TRUE.
Javad 4/15
49
O tamanho do "truque" é a melhor maneira que conheço, com uma pequena mas (para mim, essa é uma grande irritação) importante mudança no uso de parênteses.
Como a entrada da Wikipedia deixa claro, os Cs sizeofnão são uma função; é um operador . Portanto, ele não requer parênteses em torno de seu argumento, a menos que o argumento seja um nome de tipo. Isso é fácil de lembrar, pois faz com que o argumento pareça uma expressão convertida, que também usa parênteses.
Então: se você tem o seguinte:
int myArray[10];
Você pode encontrar o número de elementos com código como este:
size_t n =sizeof myArray /sizeof*myArray;
Isso, para mim, é muito mais fácil do que a alternativa entre parênteses. Também sou a favor do uso do asterisco na parte direita da divisão, pois é mais conciso do que a indexação.
Obviamente, isso também é tempo de compilação, portanto não há necessidade de se preocupar com a divisão que afeta o desempenho do programa. Portanto, use este formulário sempre que puder.
É sempre melhor usar sizeof em um objeto real quando você tiver um, em vez de em um tipo, pois você não precisará se preocupar em cometer um erro e declarar o tipo errado.
Por exemplo, digamos que você tenha uma função que gera alguns dados como um fluxo de bytes, por exemplo, em uma rede. Vamos chamar a função send()e fazer com que ela tome como argumento um ponteiro para o objeto a ser enviado e o número de bytes no objeto. Então, o protótipo se torna:
void send(constvoid*object,size_t size);
E então você precisa enviar um número inteiro, para codificá-lo assim:
int foo =4711;
send(&foo,sizeof(int));
Agora, você introduziu uma maneira sutil de se dar um tiro no pé, especificando o tipo fooem dois lugares. Se um mudar, mas o outro não, o código será quebrado. Assim, sempre faça assim:
send(&foo,sizeof foo);
Agora você está protegido. Claro, você duplica o nome da variável, mas isso tem uma alta probabilidade de quebrar de uma maneira que o compilador possa detectar, se você a alterar.
Btw, são instruções idênticas no nível do processador? Será que sizeof(int)requerem instruções menores do que sizeof(foo)?
Pacerier 21/09/13
@ Pacerier: não, eles são idênticos. Pense em int x = 1+1;versus int x = (1+1);. Aqui, os parênteses são puramente absolutamente estéticos.
quetzalcoatl
@Aidiakapi Isso não é verdade, considere os VLAs C99.
desenrole
@unwind Obrigado, estou corrigido. Para corrigir meu comentário, sizeofsempre será constante em C ++ e C89. Com matrizes de comprimento variável do C99, ele pode ser avaliado em tempo de execução.
Aidiakapi
2
sizeofpode ser um operador, mas deve ser tratado como uma função de acordo com Linus Torvalds. Concordo. Leia seu racional aqui: lkml.org/lkml/2012/7/11/103
Nitpick pequeno: o resultado da subtração do ponteiro tem tipo ptrdiff_t. (Normalmente, no sistema de 64 bits, esse será um tipo maior que int). Mesmo se você mudar intpara ptrdiff_tesse código, ele ainda arrterá um erro se ocupar mais da metade do espaço de endereço.
6134 MM
2
@MM Outro pequeno detalhe: dependendo da arquitetura do sistema, o espaço de endereço não é tão grande quanto o tamanho do ponteiro na maioria dos sistemas. O Windows, por exemplo, limita o espaço de endereço para aplicativos de 64 bits a 8 TB ou 44 bits. Portanto, mesmo se você tiver uma matriz maior que a metade do seu espaço de endereço de 4,1 TB, por exemplo, não será um erro. Somente se seu espaço de endereço exceder 63 bits nesses sistemas, é possível até encontrar esse bug. Em geral, não se preocupe.
Aidiakapi
1
@Aidiakapi no Linux x86 de 32 bits ou no Windows, com a /3Gopção de divisão de usuário / kernel 3G / 1G, que permite que as matrizes tenham até 75% do tamanho do espaço de endereço.
Ruslan
1
Considere foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];como variáveis globais. buf3[]declaração falha porque (&buf1)[1] - buf1não é uma constante.
chux - Restabelece Monica
2
Esse é um comportamento tecnicamente indefinido, pois o padrão desaprova explicitamente a exclusão de referências após o final de uma matriz (mesmo que você não tente ler o valor armazenado).
MM
26
Você pode usar o operador sizeof, mas ele não funcionará para funções, porque terá a referência do ponteiro. Você pode fazer o seguinte para encontrar o comprimento de uma matriz:
Se você conhece o tipo de dados da matriz, pode usar algo como:
int arr[]={23,12,423,43,21,43,65,76,22};int noofele =sizeof(arr)/sizeof(int);
Ou, se você não souber o tipo de dados da matriz, poderá usar algo como:
noofele =sizeof(arr)/sizeof(arr[0]);
Nota: Isso funciona apenas se a matriz não estiver definida em tempo de execução (como malloc) e a matriz não for passada em uma função. Nos dois casos, arr(nome da matriz) é um ponteiro.
int noofele = sizeof(arr)/sizeof(int);é apenas metade do caminho melhor que a codificação int noofele = 9;. O uso sizeof(arr)mantém a flexibilidade caso o tamanho da matriz mude. No entanto, sizeof(int)precisa de uma atualização, caso o tipo de arr[]alteração. Melhor usar sizeof(arr)/sizeof(arr[0])mesmo se o tipo for bem conhecido. Não está claro por que usar intfor noofelevs. size_t, o tipo retornado por sizeof().
chux - Restabelece Monica 20/05
19
A macro ARRAYELEMENTCOUNT(x)que todo mundo está usando avalia incorretamente . Realisticamente, isso é apenas uma questão delicada, porque você não pode ter expressões que resultem em um tipo de 'matriz'.
Isso realmente não tem muito a ver com o tamanho das matrizes explicitamente. Acabei de notar muitos erros ao não observar verdadeiramente como o pré-processador C funciona. Você sempre quebra o parâmetro macro, e não uma expressão pode estar envolvida.
Isto está correto; meu exemplo foi ruim. Mas isso é exatamente o que deveria acontecer. Como mencionei anteriormente p + 1, acabará como um tipo de ponteiro e invalidará toda a macro (como se você tentasse usar a macro em uma função com um parâmetro de ponteiro).
No final do dia, nesse caso em particular , a falha realmente não importa (por isso estou perdendo tempo de todos; huzzah!), Porque você não tem expressões com um tipo de 'array'. Mas, na verdade, acho importante a questão dos sutis de avaliação pré-processador.
Obrigada pelo esclarecimento. A versão original resulta em um erro em tempo de compilação. Clang reporta "o valor subscrito não é uma matriz, ponteiro ou vetor". Esse comportamento parece preferível nesse caso, embora seus comentários sobre a ordem de avaliação nas macros sejam bem aceitos.
Mark Harrison
1
Eu não tinha pensado na reclamação do compilador como uma notificação automática de um tipo incorreto. Obrigado!
3
Existe uma razão para não usar (sizeof (x) / sizeof (*x))?
seriousdev
16
Para matrizes multidimensionais , é um pouco mais complicado. Frequentemente, as pessoas definem constantes macro explícitas, ou seja,
Dependendo do tipo array, você não precisa usar sizeof(array) / sizeof(array[0])if arrayé uma matriz de char, unsigned charou signed char- Quote from C18,6.5.3.4 / 4: "Quando sizeof é aplicado a um operando que possui o tipo char, char não assinado ou char assinado , (ou uma versão qualificada), o resultado é 1. " Nesse caso, você pode simplesmente fazer o sizeof(array)que foi explicado na minha resposta dedicada .
RobertS apoia Monica Cellio
15
Tamanho de uma matriz em C:
int a[10];size_t size_of_array =sizeof(a);// Size of array aint n =sizeof(a)/sizeof(a[0]);// Number of elements in array asize_t size_of_element =sizeof(a[0]);// Size of each element in array a // Size of each element = size of type
Curioso que o código usado size_t size_of_elementainda intcom int n = sizeof (a) / sizeof (a[0]); e nãosize_t n = sizeof (a) / sizeof (a[0]);
Chux - Reintegrar Monica
1
Olá @Yogeesh HT, você pode responder à dúvida do chux. Também estou muito curioso para saber como int n = sizeof (a) / sizeof (a [0]) está fornecendo o comprimento da matriz e por que não estamos usando size_t para o comprimento da matriz. Alguém pode responder?
Cérebro
1
@Brain sizeof (a) fornece sizeof de todos os elementos presentes na matriz a sizeof (a [0]) fornece sizeof dos primeiros elementos. Suponha que a = {1,2,3,4,5}; sizeof (a) = 20bytes (se sizeof (int) = 4bytes multiplicam 5), sizeof (a [0]) = 4bytes, assim 20/4 = 5 ou seja, nenhum dos elementos
Yogeesh HT
2
@YogeeshHT Para matrizes muito grandes char a[INT_MAX + 1u];, int ncomo usadas em, int n = sizeof (a) / sizeof (a[0]);é insuficiente (é UB). O uso size_t n = sizeof (a) / sizeof (a[0]);não incorre nesse problema.
chux - Restabelece Monica
13
Eu recomendaria nunca usar sizeof(mesmo que possa ser usado) para obter qualquer um dos dois tamanhos diferentes de uma matriz, seja em número de elementos ou em bytes, que são os dois últimos casos que mostro aqui. Para cada um dos dois tamanhos, as macros mostradas abaixo podem ser usadas para torná-lo mais seguro. A razão é tornar óbvia a intenção do código para mantenedores, ea diferença sizeof(ptr)de sizeof(arr), à primeira vista (que escrito desta forma não é óbvia), de modo que os erros são então óbvio para todos a leitura do código.
Eu discordo da solução que Linus fornece, que é nunca usar a notação de matriz para parâmetros de funções.
Eu gosto da notação de matriz como documentação de que um ponteiro está sendo usado como uma matriz. Mas isso significa que uma solução infalível precisa ser aplicada para que seja impossível escrever um código de buggy.
A partir de uma matriz, temos três tamanhos que podemos querer saber:
O tamanho dos elementos da matriz
O número de elementos na matriz
O tamanho em bytes que a matriz usa na memória
O tamanho dos elementos da matriz
O primeiro é muito simples, e não importa se estamos lidando com uma matriz ou um ponteiro, porque é feito da mesma maneira.
qsort() precisa desse valor como seu terceiro argumento.
Para os outros dois tamanhos, que são o tópico da pergunta, queremos ter certeza de que estamos lidando com uma matriz e interromper a compilação, se não, porque se estivermos lidando com um ponteiro, obteremos valores errados . Quando a compilação é interrompida, poderemos ver facilmente que não estávamos lidando com uma matriz, mas com um ponteiro, e teremos que escrever o código com uma variável ou macro que armazene o tamanho da matriz. matriz atrás do ponteiro.
O número de elementos na matriz
Esta é a mais comum e muitas respostas forneceram a macro típica ARRAY_SIZE:
Matrizes com mais de PTRDIFF_MAXmembros fornecerão valores inválidos para esta versão assinada da macro, mas, ao ler C17 :: 6.5.6.9, matrizes como essa já estão brincando com fogo. Somente ARRAY_SIZEesize_t deve ser usado nesses casos.
Versões recentes de compiladores, como o GCC 8, avisam quando você aplica essa macro a um ponteiro, portanto é seguro (existem outros métodos para torná-lo seguro em compiladores mais antigos).
Ele funciona dividindo o tamanho em bytes de toda a matriz pelo tamanho de cada elemento.
Exemplos de uso:
void foo(ptrdiff_t nmemb){char buf[nmemb];
fgets(buf, ARRAY_SIZE(buf), stdin);}void bar(ptrdiff_t nmemb){int arr[nmemb];for(ptrdiff_t i =0; i < ARRAY_SSIZE(arr); i++)
arr[i]= i;}
Se essas funções não usassem matrizes, mas as obtivessem como parâmetros, o código anterior não seria compilado, portanto seria impossível ter um bug (dado que uma versão recente do compilador é usada ou que outro truque é usado) , e precisamos substituir a chamada de macro pelo valor:
void foo(ptrdiff_t nmemb,char buf[nmemb]){
fgets(buf, nmemb, stdin);}void bar(ptrdiff_t nmemb,int arr[nmemb]){for(ptrdiff_t i =0; i < nmemb; i++)
arr[i]= i;}
O tamanho em bytes que a matriz usa na memória
ARRAY_SIZE é comumente usado como uma solução para o caso anterior, mas esse caso raramente é escrito com segurança, talvez por ser menos comum.
A maneira comum de obter esse valor é usar sizeof(arr). O problema: o mesmo que o anterior; se você tiver um ponteiro em vez de uma matriz, seu programa ficará louco.
A solução para o problema envolve o uso da mesma macro de antes, que sabemos ser segura (interrompe a compilação se aplicada a um ponteiro):
Como funciona é muito simples: desfaz a divisão que o ARRAY_SIZEfaz; portanto, após cancelamentos matemáticos, você acaba com apenas um sizeof(arr), mas com a segurança adicional doARRAY_SIZE construção.
Hoje descobri que o novo aviso no GCC funciona apenas se a macro estiver definida em um cabeçalho que não seja um cabeçalho do sistema. Se você definir a macro em um cabeçalho instalado no seu sistema (normalmente /usr/local/include/ou /usr/include/) ( #include <foo.h>), o compilador NÃO emitirá um aviso (tentei o GCC 9.3.0).
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a),typeof(b))#define is_array(a)(!is_same_type((a),&(a)[0]))#defineStatic_assert_array(a)_Static_assert(is_array(a),"Not a `[]` !")#define ARRAY_SIZE(arr)( \
{ \
Static_assert_array(arr); \
sizeof(arr)/sizeof((arr)[0]); \
} \
)
Agora ARRAY_SIZE()é completamente seguro e, portanto, todos os seus derivados estarão seguros.
Atualização: libbsd fornece __arraycount() :
Libbsd fornece a macro __arraycount()em <sys/cdefs.h>que não é seguro porque falta um par de parênteses, mas podemos adicionar os parênteses nós mesmos, e, portanto, não precisa mesmo de escrever a divisão em nosso cabeçalho (por que nós duplicar o código que já existe? ) Essa macro é definida no cabeçalho do sistema; portanto, se a usarmos, somos forçados a usar as macros acima.
Alguns sistemas fornecem nitems(), em <sys/param.h>vez disso, e alguns sistemas de fornecer tanto. Você deve verificar seu sistema e usar o que possui, e talvez usar alguns condicionais do pré-processador para portabilidade e suporte aos dois.
Atualização: permita que a macro seja usada no escopo do arquivo:
Infelizmente, a ({})extensão gcc não pode ser usada no escopo do arquivo. Para poder usar a macro no escopo do arquivo, a asserção estática deve estar dentro sizeof(struct {}). Em seguida, multiplique 0para não afetar o resultado. Uma conversão para (int)pode ser boa para simular uma função que retorna (int)0(nesse caso, não é necessária, mas é reutilizável para outras coisas).
Você se importaria de explicar por que o voto negativo? Este mostra uma solução para uma construção inseguro e comum ( sizeof(arr)) que não é mostrada em outra parte: ARRAY_BYTES(arr).
Cacahuete Frito
2
ARRAY_SIZE é comum o suficiente para ser usado livremente, e ARRAY_BYTES é muito explícito em seu nome, deve ser definido ao lado de ARRAY_SIZE para que um usuário possa ver ambos facilmente e, por seu uso, não acho que alguém que esteja lendo o código tenha dúvidas sobre o que faz. O que eu quis dizer é não usar um simples sizeof, mas usar essas construções; se você quiser escrever essas construções todas as vezes, provavelmente cometerá um erro (muito comum se você copiar colar e também muito comum se você as escrever todas as vezes porque elas têm muitos parênteses) ...
Cacahuete Frito
3
..., portanto, estou na conclusão principal: uma única sizeofé claramente insegura (as razões estão na resposta), e não usando macros, mas usando as construções que forneci, a cada vez, é ainda mais insegura, então o único caminho a percorrer são macros.
Cacahuete Frito
3
@ MarkHarrison Eu sei a diferença entre ponteiros e matrizes. Mas houve momentos em que tive uma função que posteriormente refatorei em pequenas funções, e o que primeiro era uma matriz, depois um ponteiro, e esse é um ponto em que, se você esquecer de alterar o tamanho, você estraga tudo, e é fácil não ver um daqueles.
Cacahuete Frito
3
@hyde Também sei que a diferença não significa que todo mundo sabe a diferença, e por que não usar algo que basicamente remova 100% desses bugs? Esse bug quase chegou ao Linux; chegou a Linus, o que significa que passou por um exame minucioso e também significa que há a possibilidade de o mesmo bug ter entrado no Linux em outra parte do kernel, como ele diz.
Cacahuete Frito
11
"você introduziu uma maneira sutil de se dar um tiro no pé"
As matrizes 'nativas' C não armazenam seu tamanho. Portanto, é recomendável salvar o comprimento da matriz em uma variável / const separada e passá-lo sempre que passar na matriz, ou seja:
Você sempre deve evitar matrizes nativas (a menos que não consiga, nesse caso, cuidar do seu pé). Se você estiver escrevendo C ++, use o contêiner 'vector' do STL . "Em comparação com matrizes, elas fornecem quase o mesmo desempenho" e são muito mais úteis!
// vector is a template, the <int> means it is a vector of intsvector<int> numbers;// push_back() puts a new value at the end (or back) of the vectorfor(int i =0; i <10; i++)
numbers.push_back(i);// Determine the size of the array
cout << numbers.size();
Observe que isso funciona apenas para matrizes reais, não para ponteiros que apontam para matrizes.
David Schwartz
5
Se você realmente deseja fazer isso para distribuir sua matriz, sugiro implementar uma estrutura para armazenar um ponteiro para o tipo do qual você deseja uma matriz e um número inteiro representando o tamanho da matriz. Então você pode passar isso para suas funções. Apenas atribua o valor da variável da matriz (ponteiro ao primeiro elemento) a esse ponteiro. Em seguida, você pode Array.arr[i]obter o i-ésimo elemento e usar Array.sizepara obter o número de elementos na matriz.
Eu incluí algum código para você. Não é muito útil, mas você pode estendê-lo com mais recursos. Para ser sincero, no entanto, se é isso que você deseja, deve parar de usar C e usar outro idioma com esses recursos incorporados.
/* Absolutely no one should use this...
By the time you're done implementing it you'll wish you just passed around
an array and size to your functions *//* This is a static implementation. You can get a dynamic implementation and
cut out the array in main by using the stdlib memory allocation methods,
but it will work much slower since it will store your array on the heap */#include<stdio.h>#include<string.h>/*
#include "MyTypeArray.h"
*//* MyTypeArray.h
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/typedefstructMyType{int age;char name[20];}MyType;typedefstructMyTypeArray{int size;MyType*arr;}MyTypeArray;MyType new_MyType(int age,char*name);MyTypeArray newMyTypeArray(int size,MyType*first);/*
#endif
End MyTypeArray.h *//* MyTypeArray.c */MyType new_MyType(int age,char*name){MyType d;
d.age = age;
strcpy(d.name, name);return d;}MyTypeArray new_MyTypeArray(int size,MyType*first){MyTypeArray d;
d.size = size;
d.arr = first;return d;}/* End MyTypeArray.c */void print_MyType_names(MyTypeArray d){int i;for(i =0; i < d.size; i++){
printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);}}int main(){/* First create an array on the stack to store our elements in.
Note we could create an empty array with a size instead and
set the elements later. */MyType arr[]={new_MyType(10,"Sam"), new_MyType(3,"Baxter")};/* Now create a "MyTypeArray" which will use the array we just
created internally. Really it will just store the value of the pointer
"arr". Here we are manually setting the size. You can use the sizeof
trick here instead if you're sure it will work with your compiler. */MyTypeArrayarray= new_MyTypeArray(2, arr);/* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
print_MyType_names(array);return0;}
Não é possível aprovar o código que faz strcpy(d.name, name);sem manipulação de estouro.
chux - Restabelece Monica
4
A melhor maneira é salvar essas informações, por exemplo, em uma estrutura:
typedefstruct{int*array;int elements;} list_s;
Implemente todas as funções necessárias, como criar, destruir, verificar a igualdade e tudo o mais que você precisa. É mais fácil passar como parâmetro.
Alguma razão para int elementsvs. size_t elements?
chux - Restabelece Monica
3
A função sizeofretorna o número de bytes que é usado por sua matriz na memória. Se você deseja calcular o número de elementos em sua matriz, divida esse número com o sizeoftipo de variável da matriz. Digamos que int array[10];, se o número inteiro do tipo variável no seu computador for de 32 bits (ou 4 bytes), para obter o tamanho da sua matriz, faça o seguinte:
Você pode usar o &operador. Aqui está o código fonte:
#include<stdio.h>#include<stdlib.h>int main(){int a[10];int*p;
printf("%p\n",(void*)a);
printf("%p\n",(void*)(&a+1));
printf("---- diff----\n");
printf("%zu\n",sizeof(a[0]));
printf("The size of array a is %zu\n",((char*)(&a+1)-(char*)a)/(sizeof(a[0])));return0;};
Aqui está a saída da amostra
15492166721549216712---- diff----4The size of array a is 10
Não diminuí o voto, mas isso é como acertar um prego com um tijolo, porque você não notou um martelo ao seu lado. Além disso, as pessoas tendem a desaprovar o uso de variáveis não inicializadas ... mas aqui eu acho que serve bem a seu propósito.
Dmitri
2
@Dmitri variáveis não não inicializadas são acessados aqui
MM
1
Hummm. Subtração de ponteiro leva a ptrdiff_t. sizeof()resulta em size_t. C não define qual é a classificação mais ampla ou mais alta / mesma. Portanto, o tipo de quociente ((char *)(&a+1)-(char *)a)/(sizeof(a[0]))não é certamente size_te, portanto, imprimir com zpode levar a UB. Simplesmente usar printf("The size of array a is %zu\n", sizeof a/sizeof a[0]);é suficiente.
chux - Restabelece Monica
1
(char *)(&a+1)-(char *)anão é uma constante e pode ser calculado em tempo de execução, mesmo com um tamanho fixo a[10]. sizeof(a)/sizeof(a[0])é constante feito em tempo de compilação neste caso.
Além das respostas já fornecidas, quero destacar um caso especial pelo uso de
sizeof(a)/sizeof(a[0])
Se aé ou um conjunto de char, unsigned charou signed charvocê não precisa usar sizeofduas vezes desde a sizeofexpressão com um operando destes tipos sempre resultam para 1.
Citação de C18,6.5.3.4 / 4:
" Quando sizeofé aplicada a um operando que tem o tipo char, unsigned charou signed char, (ou uma versão dos mesmos qualificado) o resultado é 1."
Assim, sizeof(a) / sizeof (a[0])seria equivalente a NUMBER OF ARRAY ELEMENTS / 1se aé uma matriz do tipo char, unsigned charou signed char. A divisão até 1 é redundante.
Nesse caso, você pode simplesmente abreviar e fazer:
sizeof(a)
Por exemplo:
char a[10];size_t length =sizeof(a);
Se você quer uma prova, aqui está um link para o GodBolt .
No entanto, a divisão mantém a segurança, se o tipo mudar significativamente (embora esses casos sejam raros).
Você provavelmente prefere ainda aplicar uma macro à divisão, porque o tipo pode mudar no futuro (embora talvez improvável), e a divisão é conhecida no momento da compilação, portanto, o compilador a otimizará (se não mudar, por favor seu compilador).
Cacahuete Frito 23/04
1
@CacahueteFrito Sim, eu também pensei nisso. Eu tomei isso como uma nota lateral na resposta. Obrigado.
RobertS apoia Monica Cellio em
-1
Nota: Este pode fornecer um comportamento indefinido, conforme apontado por MM no comentário.
Esse é um comportamento tecnicamente indefinido; o *operador não pode ser aplicado a um ponteiro passado
MM
3
"comportamento indefinido" significa que o Padrão C não define o comportamento. Se você experimentá-lo em seu programa, tudo pode acontecer.
MM
@MM você *(&a+1) - a;está dizendo que é diferente do que está (&a)[1] - a;acima, não conte *(&a+1)e (&a)[1]conte como 1 após o final?
QuentinUK
@QuentinUK suas duas expressões são iguais, x[y]é definido como*(x + (y))
MM
@ MM eu pensei que sim. Mas a outra resposta, de Arjun Sreedharan, tem 38 setas para cima e isso tem -1. E a resposta de Arjun Sreedharan não menciona comportamento indefinido.
Respostas:
Sumário executivo:
Resposta completa:
Para determinar o tamanho da sua matriz em bytes, você pode usar o
sizeof
operador:No meu computador, ints têm 4 bytes de comprimento, então n é 68.
Para determinar o número de elementos na matriz, podemos dividir o tamanho total da matriz pelo tamanho do elemento da matriz. Você poderia fazer isso com o tipo, assim:
e obtenha a resposta correta (68/4 = 17), mas se o tipo de
a
alteração for alterado, você terá um erro desagradável se esquecer de alterarsizeof(int)
também.Portanto, o divisor preferido é
sizeof(a[0])
ou equivalentesizeof(*a)
, o tamanho do primeiro elemento da matriz.Outra vantagem é que agora você pode facilmente parametrizar o nome da matriz em uma macro e obter:
fonte
ARRAYSIZE
makro definido emWinNT.h
(que é puxado por outros cabeçalhos). Portanto, os usuários do WinAPI não precisam definir seu próprio makro.static int a[20];
. Mas seu comentário é útil para leitores que podem não perceber a diferença entre uma matriz e um ponteiro.O
sizeof
caminho é o caminho certo se você estiver lidando com matrizes não recebidas como parâmetros. Uma matriz enviada como parâmetro para uma função é tratada como um ponteiro; portantosizeof
, retornará o tamanho do ponteiro, em vez do tamanho da matriz.Assim, funções internas esse método não funciona. Em vez disso, sempre passe um parâmetro adicional
size_t size
indicando o número de elementos na matriz.Teste:
Saída (em um sistema operacional Linux de 64 bits):
Saída (em um sistema operacional Windows de 32 bits):
fonte
length of parameter:2
se apenas um ponteiro para o primeiro elemento da matriz for passado?(sizeof array / sizeof *array)
.Vale ressaltar que
sizeof
isso não ajuda ao lidar com um valor de matriz que se deteriorou para um ponteiro: mesmo que aponte para o início de uma matriz, para o compilador é o mesmo que um ponteiro para um único elemento dessa matriz . Um ponteiro não "lembra" mais nada sobre a matriz que foi usada para inicializá-lo.fonte
char
32 bits. Tudo o que o padrão diz é que valores inteiros de 0 a 127 podem ser representados e seu intervalo é de pelo menos -127 a 127 (o caractere é assinado) ou de 0 a 255 (o caracter não é assinado).O tamanho do "truque" é a melhor maneira que conheço, com uma pequena mas (para mim, essa é uma grande irritação) importante mudança no uso de parênteses.
Como a entrada da Wikipedia deixa claro, os Cs
sizeof
não são uma função; é um operador . Portanto, ele não requer parênteses em torno de seu argumento, a menos que o argumento seja um nome de tipo. Isso é fácil de lembrar, pois faz com que o argumento pareça uma expressão convertida, que também usa parênteses.Então: se você tem o seguinte:
Você pode encontrar o número de elementos com código como este:
Isso, para mim, é muito mais fácil do que a alternativa entre parênteses. Também sou a favor do uso do asterisco na parte direita da divisão, pois é mais conciso do que a indexação.
Obviamente, isso também é tempo de compilação, portanto não há necessidade de se preocupar com a divisão que afeta o desempenho do programa. Portanto, use este formulário sempre que puder.
É sempre melhor usar sizeof em um objeto real quando você tiver um, em vez de em um tipo, pois você não precisará se preocupar em cometer um erro e declarar o tipo errado.
Por exemplo, digamos que você tenha uma função que gera alguns dados como um fluxo de bytes, por exemplo, em uma rede. Vamos chamar a função
send()
e fazer com que ela tome como argumento um ponteiro para o objeto a ser enviado e o número de bytes no objeto. Então, o protótipo se torna:E então você precisa enviar um número inteiro, para codificá-lo assim:
Agora, você introduziu uma maneira sutil de se dar um tiro no pé, especificando o tipo
foo
em dois lugares. Se um mudar, mas o outro não, o código será quebrado. Assim, sempre faça assim:Agora você está protegido. Claro, você duplica o nome da variável, mas isso tem uma alta probabilidade de quebrar de uma maneira que o compilador possa detectar, se você a alterar.
fonte
sizeof(int)
requerem instruções menores do quesizeof(foo)
?int x = 1+1;
versusint x = (1+1);
. Aqui, os parênteses são puramente absolutamente estéticos.sizeof
sempre será constante em C ++ e C89. Com matrizes de comprimento variável do C99, ele pode ser avaliado em tempo de execução.sizeof
pode ser um operador, mas deve ser tratado como uma função de acordo com Linus Torvalds. Concordo. Leia seu racional aqui: lkml.org/lkml/2012/7/11/103Confira este link para obter explicações
fonte
ptrdiff_t
. (Normalmente, no sistema de 64 bits, esse será um tipo maior queint
). Mesmo se você mudarint
paraptrdiff_t
esse código, ele aindaarr
terá um erro se ocupar mais da metade do espaço de endereço./3G
opção de divisão de usuário / kernel 3G / 1G, que permite que as matrizes tenham até 75% do tamanho do espaço de endereço.foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];
como variáveis globais.buf3[]
declaração falha porque(&buf1)[1] - buf1
não é uma constante.Você pode usar o operador sizeof, mas ele não funcionará para funções, porque terá a referência do ponteiro. Você pode fazer o seguinte para encontrar o comprimento de uma matriz:
Código originalmente encontrado aqui: programa C para encontrar o número de elementos em uma matriz
fonte
Se você conhece o tipo de dados da matriz, pode usar algo como:
Ou, se você não souber o tipo de dados da matriz, poderá usar algo como:
Nota: Isso funciona apenas se a matriz não estiver definida em tempo de execução (como malloc) e a matriz não for passada em uma função. Nos dois casos,
arr
(nome da matriz) é um ponteiro.fonte
int noofele = sizeof(arr)/sizeof(int);
é apenas metade do caminho melhor que a codificaçãoint noofele = 9;
. O usosizeof(arr)
mantém a flexibilidade caso o tamanho da matriz mude. No entanto,sizeof(int)
precisa de uma atualização, caso o tipo dearr[]
alteração. Melhor usarsizeof(arr)/sizeof(arr[0])
mesmo se o tipo for bem conhecido. Não está claro por que usarint
fornoofele
vs.size_t
, o tipo retornado porsizeof()
.A macro
ARRAYELEMENTCOUNT(x)
que todo mundo está usando avalia incorretamente . Realisticamente, isso é apenas uma questão delicada, porque você não pode ter expressões que resultem em um tipo de 'matriz'.Realmente avalia como:
Enquanto que
Ele avalia corretamente como:
Isso realmente não tem muito a ver com o tamanho das matrizes explicitamente. Acabei de notar muitos erros ao não observar verdadeiramente como o pré-processador C funciona. Você sempre quebra o parâmetro macro, e não uma expressão pode estar envolvida.
Isto está correto; meu exemplo foi ruim. Mas isso é exatamente o que deveria acontecer. Como mencionei anteriormente
p + 1
, acabará como um tipo de ponteiro e invalidará toda a macro (como se você tentasse usar a macro em uma função com um parâmetro de ponteiro).No final do dia, nesse caso em particular , a falha realmente não importa (por isso estou perdendo tempo de todos; huzzah!), Porque você não tem expressões com um tipo de 'array'. Mas, na verdade, acho importante a questão dos sutis de avaliação pré-processador.
fonte
(sizeof (x) / sizeof (*x))
?Para matrizes multidimensionais , é um pouco mais complicado. Frequentemente, as pessoas definem constantes macro explícitas, ou seja,
Mas essas constantes também podem ser avaliadas em tempo de compilação com sizeof :
Observe que esse código funciona em C e C ++. Para matrizes com mais de duas dimensões, use
etc., ad infinitum.
fonte
fonte
array
, você não precisa usarsizeof(array) / sizeof(array[0])
ifarray
é uma matriz dechar
,unsigned char
ousigned char
- Quote from C18,6.5.3.4 / 4: "Quando sizeof é aplicado a um operando que possui o tipo char, char não assinado ou char assinado , (ou uma versão qualificada), o resultado é 1. " Nesse caso, você pode simplesmente fazer osizeof(array)
que foi explicado na minha resposta dedicada .Tamanho de uma matriz em C:
fonte
size_t size_of_element
aindaint
comint n = sizeof (a) / sizeof (a[0]);
e nãosize_t n = sizeof (a) / sizeof (a[0]);
char a[INT_MAX + 1u];
,int n
como usadas em,int n = sizeof (a) / sizeof (a[0]);
é insuficiente (é UB). O usosize_t n = sizeof (a) / sizeof (a[0]);
não incorre nesse problema.Eu recomendaria nunca usar
sizeof
(mesmo que possa ser usado) para obter qualquer um dos dois tamanhos diferentes de uma matriz, seja em número de elementos ou em bytes, que são os dois últimos casos que mostro aqui. Para cada um dos dois tamanhos, as macros mostradas abaixo podem ser usadas para torná-lo mais seguro. A razão é tornar óbvia a intenção do código para mantenedores, ea diferençasizeof(ptr)
desizeof(arr)
, à primeira vista (que escrito desta forma não é óbvia), de modo que os erros são então óbvio para todos a leitura do código.TL; DR:
must_be_array(arr)
(definido abaixo) É necessário como o-Wsizeof-pointer-div
buggy (a partir de abril / 2020):Houve erros importantes em relação a este tópico: https://lkml.org/lkml/2015/9/3/428
Eu discordo da solução que Linus fornece, que é nunca usar a notação de matriz para parâmetros de funções.
Eu gosto da notação de matriz como documentação de que um ponteiro está sendo usado como uma matriz. Mas isso significa que uma solução infalível precisa ser aplicada para que seja impossível escrever um código de buggy.
A partir de uma matriz, temos três tamanhos que podemos querer saber:
O tamanho dos elementos da matriz
O primeiro é muito simples, e não importa se estamos lidando com uma matriz ou um ponteiro, porque é feito da mesma maneira.
Exemplo de uso:
qsort()
precisa desse valor como seu terceiro argumento.Para os outros dois tamanhos, que são o tópico da pergunta, queremos ter certeza de que estamos lidando com uma matriz e interromper a compilação, se não, porque se estivermos lidando com um ponteiro, obteremos valores errados . Quando a compilação é interrompida, poderemos ver facilmente que não estávamos lidando com uma matriz, mas com um ponteiro, e teremos que escrever o código com uma variável ou macro que armazene o tamanho da matriz. matriz atrás do ponteiro.
O número de elementos na matriz
Esta é a mais comum e muitas respostas forneceram a macro típica ARRAY_SIZE:
Como o resultado de ARRAY_SIZE é comumente usado com variáveis assinadas do tipo
ptrdiff_t
, é bom definir uma variante assinada dessa macro:Matrizes com mais de
PTRDIFF_MAX
membros fornecerão valores inválidos para esta versão assinada da macro, mas, ao ler C17 :: 6.5.6.9, matrizes como essa já estão brincando com fogo. SomenteARRAY_SIZE
esize_t
deve ser usado nesses casos.Versões recentes de compiladores, como o GCC 8, avisam quando você aplica essa macro a um ponteiro, portanto é seguro (existem outros métodos para torná-lo seguro em compiladores mais antigos).
Ele funciona dividindo o tamanho em bytes de toda a matriz pelo tamanho de cada elemento.
Exemplos de uso:
Se essas funções não usassem matrizes, mas as obtivessem como parâmetros, o código anterior não seria compilado, portanto seria impossível ter um bug (dado que uma versão recente do compilador é usada ou que outro truque é usado) , e precisamos substituir a chamada de macro pelo valor:
O tamanho em bytes que a matriz usa na memória
ARRAY_SIZE
é comumente usado como uma solução para o caso anterior, mas esse caso raramente é escrito com segurança, talvez por ser menos comum.A maneira comum de obter esse valor é usar
sizeof(arr)
. O problema: o mesmo que o anterior; se você tiver um ponteiro em vez de uma matriz, seu programa ficará louco.A solução para o problema envolve o uso da mesma macro de antes, que sabemos ser segura (interrompe a compilação se aplicada a um ponteiro):
Como funciona é muito simples: desfaz a divisão que o
ARRAY_SIZE
faz; portanto, após cancelamentos matemáticos, você acaba com apenas umsizeof(arr)
, mas com a segurança adicional doARRAY_SIZE
construção.Exemplo de uso:
memset()
precisa desse valor como seu terceiro argumento.Como antes, se o array for recebido como um parâmetro (um ponteiro), ele não será compilado e teremos que substituir a chamada de macro pelo valor:
Atualização (23 / abr / 2020):
-Wsizeof-pointer-div
é de buggy :Hoje descobri que o novo aviso no GCC funciona apenas se a macro estiver definida em um cabeçalho que não seja um cabeçalho do sistema. Se você definir a macro em um cabeçalho instalado no seu sistema (normalmente
/usr/local/include/
ou/usr/include/
) (#include <foo.h>
), o compilador NÃO emitirá um aviso (tentei o GCC 9.3.0).Então, temos
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
e queremos torná-lo seguro. Vamos precisar de_Static_assert()
extensões C11 e GCC: Declarações e declarações em expressões , __builtin_types_compatible_p :Agora
ARRAY_SIZE()
é completamente seguro e, portanto, todos os seus derivados estarão seguros.Atualização: libbsd fornece
__arraycount()
:Libbsd fornece a macro
__arraycount()
em<sys/cdefs.h>
que não é seguro porque falta um par de parênteses, mas podemos adicionar os parênteses nós mesmos, e, portanto, não precisa mesmo de escrever a divisão em nosso cabeçalho (por que nós duplicar o código que já existe? ) Essa macro é definida no cabeçalho do sistema; portanto, se a usarmos, somos forçados a usar as macros acima.Alguns sistemas fornecem
nitems()
, em<sys/param.h>
vez disso, e alguns sistemas de fornecer tanto. Você deve verificar seu sistema e usar o que possui, e talvez usar alguns condicionais do pré-processador para portabilidade e suporte aos dois.Atualização: permita que a macro seja usada no escopo do arquivo:
Infelizmente, a
({})
extensão gcc não pode ser usada no escopo do arquivo. Para poder usar a macro no escopo do arquivo, a asserção estática deve estar dentrosizeof(struct {})
. Em seguida, multiplique0
para não afetar o resultado. Uma conversão para(int)
pode ser boa para simular uma função que retorna(int)0
(nesse caso, não é necessária, mas é reutilizável para outras coisas).fonte
sizeof(arr)
) que não é mostrada em outra parte:ARRAY_BYTES(arr)
.sizeof
, mas usar essas construções; se você quiser escrever essas construções todas as vezes, provavelmente cometerá um erro (muito comum se você copiar colar e também muito comum se você as escrever todas as vezes porque elas têm muitos parênteses) ...sizeof
é claramente insegura (as razões estão na resposta), e não usando macros, mas usando as construções que forneci, a cada vez, é ainda mais insegura, então o único caminho a percorrer são macros."você introduziu uma maneira sutil de se dar um tiro no pé"
As matrizes 'nativas' C não armazenam seu tamanho. Portanto, é recomendável salvar o comprimento da matriz em uma variável / const separada e passá-lo sempre que passar na matriz, ou seja:
Você sempre deve evitar matrizes nativas (a menos que não consiga, nesse caso, cuidar do seu pé). Se você estiver escrevendo C ++, use o contêiner 'vector' do STL . "Em comparação com matrizes, elas fornecem quase o mesmo desempenho" e são muito mais úteis!
Consulte: http://www.cplusplus.com/reference/stl/vector/
fonte
enum
declaração.fonte
Se você realmente deseja fazer isso para distribuir sua matriz, sugiro implementar uma estrutura para armazenar um ponteiro para o tipo do qual você deseja uma matriz e um número inteiro representando o tamanho da matriz. Então você pode passar isso para suas funções. Apenas atribua o valor da variável da matriz (ponteiro ao primeiro elemento) a esse ponteiro. Em seguida, você pode
Array.arr[i]
obter o i-ésimo elemento e usarArray.size
para obter o número de elementos na matriz.Eu incluí algum código para você. Não é muito útil, mas você pode estendê-lo com mais recursos. Para ser sincero, no entanto, se é isso que você deseja, deve parar de usar C e usar outro idioma com esses recursos incorporados.
fonte
strcpy(d.name, name);
sem manipulação de estouro.A melhor maneira é salvar essas informações, por exemplo, em uma estrutura:
Implemente todas as funções necessárias, como criar, destruir, verificar a igualdade e tudo o mais que você precisa. É mais fácil passar como parâmetro.
fonte
int elements
vs.size_t elements
?A função
sizeof
retorna o número de bytes que é usado por sua matriz na memória. Se você deseja calcular o número de elementos em sua matriz, divida esse número com osizeof
tipo de variável da matriz. Digamos queint array[10];
, se o número inteiro do tipo variável no seu computador for de 32 bits (ou 4 bytes), para obter o tamanho da sua matriz, faça o seguinte:fonte
Você pode usar o
&
operador. Aqui está o código fonte:Aqui está a saída da amostra
fonte
ptrdiff_t
.sizeof()
resulta emsize_t
. C não define qual é a classificação mais ampla ou mais alta / mesma. Portanto, o tipo de quociente((char *)(&a+1)-(char *)a)/(sizeof(a[0]))
não é certamentesize_t
e, portanto, imprimir comz
pode levar a UB. Simplesmente usarprintf("The size of array a is %zu\n", sizeof a/sizeof a[0]);
é suficiente.(char *)(&a+1)-(char *)a
não é uma constante e pode ser calculado em tempo de execução, mesmo com um tamanho fixoa[10]
.sizeof(a)/sizeof(a[0])
é constante feito em tempo de compilação neste caso.A resposta mais simples:
fonte
Uma solução mais elegante será
fonte
Além das respostas já fornecidas, quero destacar um caso especial pelo uso de
Se
a
é ou um conjunto dechar
,unsigned char
ousigned char
você não precisa usarsizeof
duas vezes desde asizeof
expressão com um operando destes tipos sempre resultam para1
.Citação de C18,6.5.3.4 / 4:
Assim,
sizeof(a) / sizeof (a[0])
seria equivalente aNUMBER OF ARRAY ELEMENTS / 1
sea
é uma matriz do tipochar
,unsigned char
ousigned char
. A divisão até 1 é redundante.Nesse caso, você pode simplesmente abreviar e fazer:
Por exemplo:
Se você quer uma prova, aqui está um link para o GodBolt .
No entanto, a divisão mantém a segurança, se o tipo mudar significativamente (embora esses casos sejam raros).
fonte
Nota: Este pode fornecer um comportamento indefinido, conforme apontado por MM no comentário.
Para mais detalhes, veja aqui e também aqui .
fonte
*
operador não pode ser aplicado a um ponteiro passado*(&a+1) - a;
está dizendo que é diferente do que está(&a)[1] - a;
acima, não conte*(&a+1)
e(&a)[1]
conte como 1 após o final?x[y]
é definido como*(x + (y))