
		paulo1205
		
		(usa Ubuntu)
		
		Enviado em 09/04/2017 - 00:42h 
		SarusKant escreveu:
vetor de carácteres com limite de 4 carácteres.
char arr[4];
arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';
arr[3] = '\0'; //Indica o fim do vetor. 
  
Falso.  O byte nulo indica apenas o fim da string.
vetor de carácteres dinâmico.
char *arr;
arr = (char*) malloc(sizeof(char)*1+1); //Alocando somente para 1 carácter. 
  
Não.  Você aloca espaço para dois caracteres (um que vai conter a letra, e outro que vai indicar o fim da string).
E o faz, aliás, com uma redundância e uma inconsistência.  A redundância é que “
sizeof(char)” é sempre, por definição, igual a 1.  E a inconsistência é que, se você está preocupado com “
sizeof(char)”, deveria ter feito “sizeof(char)*(1+1)”.
Outro problema é que você assume que a alocação vai sempre ter sucesso.  Um programa preocupado com robustez deveria considerar a possibilidade de 
malloc() falhar.
 arr=malloc(2);
if(arr==NULL){
  // Trata o erro de alocação.  No caso, eu aborto o programa.
  fprintf(stderr, "Erro de alocação de memória.\n");
  exit(1);
} 
Mais ainda: em C, a conversão de tipo do valor retornado por 
malloc() para 
char * é desnecessária e indesejável.  Em C++, ela teria de ser feita, mas a forma de a fazer em C++ seria com um operador de conversão de tipo nativo do C++, pois a conversão ao estilo de C é considerada insegura (ela converte na marra mesmo algumas coisas que seriam absurdas).  Veja como seria a conversão em C++.
arr=static_cast<char *>(malloc(2)); 
Contudo, isso também seria considerado mau uso de C++.  C++ oferece o operador 
new [] para alocação de memória, que é totalmente seguro quanto ao tipo de ponteiro.  A forma que alguém em C++ usaria para fazer a alocação de dados seria a seguinte.
arr=new char[2]; 
Uma desvantagem disso, porém, seria o fato de que não existe realocação de dados alocados com 
new.  No entanto, existem classes que cuidam de fazer esse tipo de coisa.  A mais comum delas é 
std::vector.  Nesse caso, você deixaria de declarar 
arr como um ponteiro, e o declararia como 
std::vector<char>.
std::vector arr;
/* ... */
arr.resize(2); 
Se o objetivo, no entanto, for usar strings, melhor seria usar 
std::string para sua variável.
arr[0] = 'a';
arr[1] = '\0';
arr = (char*) realloc(arr,sizeof(char)*4); //Realocando para 4 carácteres. 
  
Aqui, além de repetir alguns dos erros apontados acima com o uso de 
malloc(), você cometeu mais um, que infelizmente é um erro muito comum: usar o mesmo ponteiro que está sendo redimensionado como destino da atribuição do valor de retorno.
O motivo para que isso seja considerado um erro é que a realocação pode falhar.  Se a realocação falhar, a função 
realloc() garante a preservação da alocação e do conteúdo anterior referenciado pelo ponteiro, e sinaliza a falha através do valor de retorno da função, devolvendo um ponteiro nulo.  Só que, como você usou a mesma variável ponteiro como destino da atribuição do valor retornado, se esse valor indicar uma falha de alocação, você vai sobrescrever o ponteiro com o valor de sinalização de erro, perdendo a referência original ao dado que 
realloc() teve o cuidado de preservar.
A maneira correta de fazer o que você tentou fazer seria a seguinte (em C, não em C++; trato de C++ mais a diante):
 char *ptr=realloc(arr, 4);
if(ptr!=NULL){
  // Realocação bem sucedida: sobrescrevo ‘arr’ com novo valor de ponteiro.
  arr=ptr;
  // Modifico a string "a\0" para "abc\0".
  strcat(arr, "bc");
}
// Se realocação  tiver falhado, a string original é preservada.
// Em todo caso, neste ponto, ‘arr’ aponta para uma string válida. 
Em C++, se você tiver usado 
std::vector<char> ou 
std::string, basta fazer o seguinte.
arr.resize(4); 
arr[1] = 'b';
arr[2] = 'c';
arr[3] = '\0'; 
Obs. Quando se usa * se deve liberar memória ao fim do uso da variável.
free(arr); 
  
Outra vantagem de usar 
std::vector ou 
std::string é não ter de se preocupar com isso.
Por outro lado, se se preferir a alocação com 
new [], deve-se fazer a desalocação com 
delete[].
delete[] arr;