paulo1205
(usa Ubuntu)
Enviado em 11/12/2012 - 15:21h
1 e 2)
Eu recomendo que você leia a documentação para aprender com detalhes. Resumidamente, a diferença entre
strcpy () e
strncpy () é que a segunda tem um campo a mais que informa o número máximo de caracteres que serão copiados. A razão pela qual você deve preferir
strncpy () a
strcpy () é que é muito fácil, com esta última, exceder o tamanho máximo da string destino, e escrever bytes em áreas de memória inválidas, provocando falhas impredizíveis no programa, ou áreas ocupadas por outras variáveis, corrompendo-as. Por exemplo, o código abaixo demonstra uma corrpução desse tipo.
#include <stdio.h>
#include <string.h>
int main(void){
int a=0xAAAAAAAA, b=0xBBBBBBBB;
char str[4]="str";
int c=0xCCCCCCCC, d=0xDDDDDDDD;
printf("Antes: a=%X, b=%X, str=\"%s\", c=%X, d=%X\n", a, b, str, c, d);
strcpy(str, "Este aqui e um texto mais longo do que o tamanho do destino.");
printf("Depois: a=%X, b=%X, str=\"%s\", c=%X, d=%X\n", a, b, str, c, d);
return 0;
}
Ao compilar e executar o programa, eu recebo o seguinte.
$ gcc lixo.c
$ ./a.out
Antes: a=AAAAAAAA, b=BBBBBBBB, str="str", c=CCCCCCCC, d=DDDDDDDD
Depois: a=AAAAAAAA, b=BBBBBBBB, str="Este aqui e um texto mais longo do que o tamanho do destino.", c=CCCCCCCC, d=DDDDDDDD
*** stack smashing detected ***: ./a.out terminated
Segmentation fault (core dumped)
Se eu transformar as variáveis em globais, movendo as três primeiras linhas de
main () para fora do corpo da função, eu recebo o seguinte.
$ gcc lixo.c
$ ./a.out
Antes: a=AAAAAAAA, b=BBBBBBBB, str="str", c=CCCCCCCC, d=DDDDDDDD
Depois: a=AAAAAAAA, b=BBBBBBBB, str="Este aqui e um texto mais longo do que o tamanho do destino.", c=75716120, d=20652069
Em ambos os casos, se eu tivesse usando
strncpy () com o tamanho máximo apropriado para a string destino, conforme mostrei na mensagem anterior, o conteúdo de
str ficaria apenas como "Est", não provocando stack smashing nem corrompendo os valores de outras variáveis.
3) Não. O
origem+3 significa pular os três primeiros elementos de
origem , começando, portanto, a contar do quarto elemento.
4) Por convenção, toda string em C termina obrigatoriamente com um byte nulo (valor zero). No programa acima, você vê que eu faço
str[4]="str" porque ela de fato tem quatro elementos, que são os bytes 's', 't', 'r' e nulo (em C, o byte nulo pode ser escrito como o caráter de barra invertida ("\") seguido de zero, mas o fórum do VoL engasga quando se escrevem esses dois caracteres aqui). Assim, forçar o n-ésimo elemento (geralmente o último) de um array de caracteres a ter o byte nulo é uma forma de garantir que todas as funções do sistema conseguirão determinar o fim da string com sucesso.
Para você ver o problema de esquecer-se de garantir isso, veja o seguinte código, que deliberadamente cria um array que não tem o byte nulo na última posição de memória alocada, e, logo em seguida, a saída correspondente quando eu o compilei e executei na minha máquina (note que o tamanho e os bytes adicionais que aparecem são meio que por acaso; é imprevisível o que vai sair se você fizer o mesmo na sua máquina, podendo até dar erro fatal no programa).
#include <stdio.h>
#include <string.h>
int main(void){
/* Note que o array abaixo nao atende as convencoes de uma string. */
char array[4]={'a', 'b', 'c', 'd'};
printf("Comprimento de array: %zd bytes.\nConteudo: \"%s\"\n", strlen(array), array);
return 0;
}
$ gcc lixo.c
$ ./a.out
Comprimento de array: 6 bytes.
Conteudo: "abcdÿ~"