2017-02-09 2 views
0

그들이 아니었다면, 그것은 잘 작동하지만 나는 단어 "페로을"수정을 요청하려는 경우 사용자가 오류를 제공 printf("Ingrese una palabra: ");scanf("%s",(vector+1)); , 나는 다음 코드를하고 난 두 줄의 코드에 문제가 있습니다.이중 포인터 안에 저장되지 않는 이유는 무엇입니까?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() 
{ 
    int i,j,a; 
    char **vector; 

    vector = (char**)malloc(2*sizeof(char*)); 

    *(vector) = "hola"; 
    *(vector + 1) = "perro"; 

    //HERE IS THE PROBLEM 
    printf("Ingrese una palabra: "); 
    scanf("%s",(vector+1)); 
    // 

    puts("\nImprimiendo caracter a caracter:"); 
    for(i=0;i<2;i++) 
    { 
     for(j=0; j<strlen(*(vector+i)) ; j++) 
     { 
      printf("%c",*(*(vector+i)+j)); 
     } 
     puts(""); 
    } 

    puts("\nImprimiendo completo:"); 
    printf("%s\n",*vector); 
    printf("%s",*(vector+1)); 

    free(vector); 

    return 0; 
} 
+0

무엇을하려고하는지 설명해 주시겠습니까? –

+3

'(vector + 1)'이 포인터에 대한 포인터가 아닌가? scanf에 대한 포인터를 전달하지 않겠습니까? (*'(vector + 1)'일까?) 두 번째로 문자열은 읽기 전용이기 때문에 수정하려고 시도 할 때 –

+2

'scanf ("% s", (vector + 1));에서 읽기 전용 메모리 (@MichaelPetch 주석에 따라) * 문자열 리터럴 *에 대한 포인터로 포인터를 초기화했기 때문에 가능한 경우에도 입력은 doggish * perro *의 5 자 길이로 제한됩니다. –

답변

-1

초기화하지 않고 2 명의 퀴즈에 액세스하고 있습니다. 문자를 포함하기 때문에 2 개의 벡터 공간을 예약해야합니다.

+0

그는 char * 포인터의 배열 (2 개의'char *'포인터를위한 공간)을 생성 한 다음 배열의 처음 두 요소를 두 개의 문자열 주소로 초기화했다. 따라서 배열은 2 개의'char *'에 대해 적절한 공간을 할당 받고 (malloc을 사용하여), 두 배열 항목 모두 초기화됩니다. 불행하게도 그들은 읽기 전용 메모리에있을 포인터로 초기화되고 포인터는'scanf'에서 포인터 역 참조를 수행하는 것을 잊었습니다. –

+0

포인터가 litteral 문자열에 할당되었으므로 수정할 수 없다고 말합니까? 그게 내가 초기화되지 않음을 의미합니다 .. 나는 제대로 추가해야합니다 .. – claudio06

1

*(vector + 1)과 같은 내용은 불필요하게 읽기가 어렵습니다. vector[1]을 쓸 수 있습니다. 어쩌면 당신은 운동으로하고 있지만 어쩌면 나는 모든 것을 배열 구문으로 변환 할 것입니다.

두 가지 문제가 있습니다. 첫째는 이것이다 : (당신은 컴파일러 경고를 -Wall으로 전원을 켜십시오 그들 모두가 해결되지 않으면)

test.c:17:16: warning: format specifies type 'char *' but the argument has type 'char **' [-Wformat] 
    scanf("%s",(vector+1)); 
      ~~ ^~~~~~~~~~ 

:

scanf("%s",(vector+1)); 

이것은 컴파일러 경고를 생성합니다.

scanfchar * 문자열을 원합니다. 하지만 문자열의 목록 인 vector을주고 포인터 하나 이상을 이동했습니다.

scanf 어쨌든 문자열을 밀어 넣으려고합니다. vector은 64 비트 시스템에서 8 바이트 인 2 * sizeof(char*) 만 할당되었습니다. 1 char * 또는 4 바이트를 이동하여 4 바이트 만 남았습니다. 그래서 그것은 "안전하게"거기에 3자를 더하고, null 바이트를 더할 수 있습니다. 하지만 C는 지저분한 편이므로 scanf은 운영체제가 멈추지 않고 더 많은 정보를 제공 할 수 있습니다. 당신이 문자열로 vector[1]를 사용하려고하면 perro에서 char * 포인팅 문자 123 및 null 바이트로 덮어 쓴해야한다 무엇 때문에

$ ./test 
Ingrese una palabra: 123 

Imprimiendo caracter a caracter: 
hola 
Segmentation fault: 11 

그것은, 세그먼테이션 폴트 (segfault). 그것을 메모리 포인터로 사용하여 폭발시킵니다.

대신에 char *을 전달해야합니다. 즉 *(vector+1)이거나 간단히 vector[1]입니다.

scanf("%s", vector[1]); 

이 우리의 다음 문제를 우리에게 가져다 : 당신은 오직, vector에 대한 문자열 목록을 메모리를 할당. 문자열 자체에 메모리를 할당하지 않았습니다! 목록에 상수를 할당하는 것은 대용 할 수 없습니다. 수정 된 코드를 실행하자마자 버스 오류가 발생합니다.

$ ./test 
Ingrese una palabra: adlskfj 
Bus error: 10 

vector[1]는 상수 문자열 perro이 포함되어 있기 때문입니다. 이것에 대한 경고도 받았습니다.

"이봐, 이것은 상수 문자열이지만, 상수가 아닌 것처럼 사용하고있다"는 의미입니다.

scanf은 덮어 쓰기를 시도하여 실패합니다.실제로 컴파일 된 바이너리의 일부를 가리키기 때문에 "메모리"를 덮어 쓸 수 없습니다. 포인터를 인쇄하면 그가 앞으로 다른 표정을 보게 될 것입니다.

printf("%p\n", vector[1]); 
printf("%p\n", vector); 

$ ./test 
0x109ce7f51 
0x7ff664c08d90 

내가 16 진수 편집기와 바이너리 볼

, 나는 (당신이 다른 위치에있을 것입니다) 프로그램의 다른 문자열 상수와 함께 위치 00000f51에서 perro을 찾을 수 있습니다.

00000f40: ffff 6841 0000 00e9 b4ff ffff 686f 6c61 ..hA........hola 
00000f50: 0070 6572 726f 0025 700a 0049 6e67 7265 .perro.%p..Ingre 
00000f60: 7365 2075 6e61 2070 616c 6162 7261 3a20 se una palabra: 
00000f70: 0025 7300 0a49 6d70 7269 6d69 656e 646f .%s..Imprimiendo 
00000f80: 2063 6172 6163 7465 7220 6120 6361 7261 caracter a cara 
00000f90: 6374 6572 3a00 2563 0000 0a49 6d70 7269 cter:.%c...Impri 
00000fa0: 6d69 656e 646f 2063 6f6d 706c 6574 6f3a miendo completo: 
00000fb0: 0025 730a 0000 0000 0100 0000 1c00 0000 .%s............. 

당신은 0x109ce7f51에서 0xf51을 볼 수 있습니다. 바이너리에서 읽으려고 C에 알려주는 마법 메모리 위치이고 오프셋은 0xf51입니다. 0x7ff664c08d90은 힙의 읽기/쓰기 메모리를 가리키고 있습니다.

하는 문자열 배열을 저장하려면 목록 과 문자열 메모리를 할당해야합니다. vector[1] = "perro" 상수 문자열로 할당 된 메모리 포인터를 대체 할 것이다 당신은 다시 버스 오류가 될 거라고

vector = malloc(2*sizeof(char*)); 
for(i = 0; i < 2; i++) { 
    vector[i] = malloc(256 * sizeof(char*)); 
} 

printf("Ingrese una palabra: "); 
scanf("%s",vector[1]); 

참고.

또한 I don't cast malloc에 유의하십시오.

관련 문제