Edição didática em português. O código e suas saídas preservam o original.
Array de ponteiros em C
Diferencie um array de endereços de um ponteiro para um array e acesse os objetos corretamente.

int *p[3] declara um array de três ponteiros para int. Já int (*p)[3] declara um ponteiro para um array de três inteiros. Os parênteses mudam qual parte do declarador é agrupada primeiro.
Cada elemento do array de ponteiros precisa de um endereço válido antes de ser desreferenciado. Os objetos apontados podem estar em lugares diferentes e precisam continuar existindo enquanto são usados. Para imprimir um endereço com %p, converta o argumento para void *.
Um array de ponteiros para strings não é uma matriz retangular de caracteres. Se apontar para literais, utilize const char * e não tente modificá-los. Desenhe cada ponteiro e seu objeto para conferir a interpretação.
Código C
#include <stdio.h>
int main(void)
{
int first = 10;
int second = 20;
int third = 30;
int *items[] = {&first, &second, &third};
size_t count = sizeof items / sizeof items[0];
*items[1] = 25;
for (size_t i = 0; i < count; ++i) {
printf("items[%zu] points to %d\n", i, *items[i]);
}
printf("second is now %d\n", second);
return 0;
}Abrir no compiladorPerguntas frequentes
Por que o código e a saída continuam em inglês?
Palavras-chave, identificadores e textos verificados pelos testes são preservados para não alterar o programa. As explicações e os controles estão traduzidos.