Enviado em 04/01/2019 - 01:31h 
		A primeira pergunta é análoga a “a partir de que momento você pode dizer que é fluente em Inglês?” (ou Alemão, ou Russo, ou Mandarim, ou Sânscrito etc.).  É difícil dizer com certeza, mas tipicamente envolve conhecer suficientemente bem:
  • seu vocabulário, ou ao menos aquela parte do vocabulário que é mais comum ou ligado à área do seu interesse (no caso de uma linguagem de programação simples como o C, o vocabulário é um conjunto pequeno, fácil de ser totalmente conhecido);
  • a gramática, com suas regras sintáticas, que determinam onde e como é possível dispor os vocábulos, e extrair sentidos claros a partir dessa disposição; e
  • o linguajar e as expressões típicos de outros falantes do idioma (que, no caso do C, pode incluir a biblioteca padrão e as formas usuais de fazer determinadas operações comuns, tais como incrementar o valor de uma variável, varrer um 
array , passar argumentos por valor e por referência etc.).
“Suficientemente bem” não quer dizer conhecer tudo, mas saber bem aquilo que é mais comum no dia-a-dia, e estar apto para (re)aprender o que é menos comum sem ter de fazer um esforço muito grande.
Vetores em C são normalmente chamados de 
arrays , e são dados compostos por vários elementos de mesmo tipo e dispostos em posições adjacentes na memória.  São exemplos de 
arrays  as seguintes declarações.
char nome[50];  // Declara ‘nome’ como array com 50 elementos do tipo char. 
Ponteiros, por outro lado, são valores que indicam um endereço de memória e, ao mesmo tempo, carregam a informação de qual tipo de dado estará guardado nesse endereço, se tal endereço for válido no contexto de execução do programa.
Você possivelmente notou que, nas definições que eu coloquei acima, eu falei de 
arrays  e ponteiros como 
dados  ou como 
valores , e não como tipos de dados ou como categorias de variáveis.  Isso foi proposital.  Não porque tais tipos não existam (nas declarações de exemplo eu inclusive digo quais são os tipos de cada 
array  declarado), mas porque é possível produzir ponteiros em C sem declarar qualquer variável de um tipo ponteiro e também porque um ponteiro pode ser usado para indicar transitoriamente um (ou um pedaço de um) 
array .
Esse uso intercambiável em certas situações não significa que 
arrays  e ponteiros são equivalentes ou que possam sempre trocar de lugar um com o outro, ainda que esse seja um ponto de confusão para muitas pessoas que estão aprendendo C.  Esse é, aliás, é um aspecto que pode entrar na avaliação do grau de fluência que alguém tem com o C.
O fato é que tanto variáveis de tipos ponteiros quanto variáveis de tipos 
arrays  produzem valores de tipos ponteiros quando tais variáveis aparecem como parte de uma expressão (com apenas três exceções no caso de 
arrays , que são no momento da declaração, com ou sem atribuição de valores iniciais aos elementos, e quando a variável é passada como argumento dos operadores unários 
&  e 
sizeof ).  Um ponteiro para dado do tipo 
X  é substituído pelo valor do endereço do dado do tipo 
X  ao qual se refere, e um 
array  para dado do tipo 
X  produz um valor que é equivalente a um ponteiro para seu primeiro elemento.  Uma restrição a mais para os ponteiros obtidos a partir de 
arrays  é o fato de que seu decaimento para ponteiros gera sempre 
rvalues , o que significa que uma variável declarada como 
array  não pode ser substituída com outro 
array  (nem muito menos ponteiro) após ter sido declarada, ao passo que uma variável ponteiro que não tenha sido declarada como constante pode ter seu valor livremente modificado várias vezes ao longo do programa.