*(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));
이것은 컴파일러 경고를 생성합니다.
scanf
은 char *
문자열을 원합니다. 하지만 문자열의 목록 인 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
에 유의하십시오.
무엇을하려고하는지 설명해 주시겠습니까? –
'(vector + 1)'이 포인터에 대한 포인터가 아닌가? scanf에 대한 포인터를 전달하지 않겠습니까? (*'(vector + 1)'일까?) 두 번째로 문자열은 읽기 전용이기 때문에 수정하려고 시도 할 때 –
'scanf ("% s", (vector + 1));에서 읽기 전용 메모리 (@MichaelPetch 주석에 따라) * 문자열 리터럴 *에 대한 포인터로 포인터를 초기화했기 때문에 가능한 경우에도 입력은 doggish * perro *의 5 자 길이로 제한됩니다. –