보시다시피 일부러 에러를 유도하기 위해서 type도 다르게 했고, 메모리도 형편없이 작게 주었습니다.
그런데 왜 이게 재대로 나오는 건지 모르겠습니다.
이전에 char형에 256 이상 입력하면 숫자가 다른게 튀어나와서 그걸 포인터에도 기대하고 메모리 할당도 1byte만 했는데 데, 포인터는 왜...되는걸까요?T..T
그리고 포인터 정의할때 형(int, char)은 그냥 포인터가 지시하는 값의 형을 프로그레머가 참고하라는 의미인지요?
8byte 주소값이고, 값이 거기 저장되는 것도 아닌데다가, 메모리도 할당해줄 수 있다면 저기서 정의하는 type이라는 것은 결국 *p의 형이라는 의미 아니겠습니까? 포인터에서 형을 정의했다고 해서 포인터 자체의 메모리가 변하는 것도 아닌데
실제로
int *p;
char n;
p=(int*)calloc(1, 1);
p=&n
printf("%c", *p);
scanf("%c", &n);
printf("Input number\t");
해도 잘 나옵니다.
(IP보기클릭)220.117.***.***
(IP보기클릭)220.117.***.***
지금 p=&n;을 쓰셔서 calloc으로 할당한 1byte 메모리를 쓰고계시지 않지만, calloc의 1byte에 값을 입력하고 싶다면 int *p; p=(int*)calloc(1, 1); scanf("%d", p); printf("%d", *p); 라고 쓰셔야 합니다. 이 코드는 분명히 잘못된 코드이지만, 실제로는 동작할 수도 있고, 안 할수도 있습니다. 동작한다고 해도 문제가 있는 코드입니다. p=&n;을 삭제하고, scan에 p를 썼습니다. 이렇게 쓰면 p는 calloc에서 할당한 메모리의 위치에 1000000을 입력하게 됩니다. 이 경우, 할당받은 메모리는 1byte지만, scanf는 그 뒤에 있는 할당받지 않은 3byte까지 값을 입력합니다. 할당받지 않은 메모리에 값을 입력할 때의 동작은 알 수 없습니다. 컴파일러에 따라서, OS에 따라서 달라질 수 있습니다. 다만 할당받지 않은 메모리에 값을 썼는데도 '우연히' 문제가 없었다면, 남은 3byte를 합친 4byte에 1000000이라는 값이 입력됩니다. 동일하게 printf도, 4byte를 읽어서 값을 표시하려고 하고, '우연히' 문제가 없어서 1000000을 출력할 수 있습니다. scanf와 printf는 할당받지 않은 메모리를 이용해도 될까요? 절대 그렇지 않지만, scanf와 printf는 시킨 일을 했을 뿐입니다. 지정해준 주소의 메모리가 할당 됐는지 안 됐는지 scanf와 printf는 모릅니다. | 21.12.26 00:38 | |
(IP보기클릭)59.16.***.***
감사합니다. 고민거리를 던져준 답변 감사드립니다. 메리크리스마스. | 21.12.26 00:49 | |
(IP보기클릭)220.117.***.***
int main() { char c1 = 0x00; char c2 = 0x00; char c3 = 0x00; char c4 = 0x00; int *p = (int*)&c1; printf("%x\n", &c1); printf("%x\n", &c2); printf("%x\n", &c3); printf("%x\n", &c4); *p = 0x41424344; printf("%c\n", c1); printf("%c\n", c2); printf("%c\n", c3); printf("%c\n", c4); return 0; } 혹시 이 코드를 한번 실행시켜서 결과를 알려주실 수 있을까요? 코드 블럭의 결과가 궁금합니다. | 21.12.26 00:51 | |
(IP보기클릭)59.16.***.***
| 21.12.26 00:58 | |
(IP보기클릭)220.117.***.***
오... 예상하던 결과와 다른 결과가 나왔군요. 하지만 좋습니다. 일단 이게 무슨 코드냐 하면, 4개의 char 변수를 선언하고, 1개의 int 포인터 변수를 선언하고, int 포인터에 c1의 포인터를 지정했습니다. 즉, p는 int*지만 char 값인 c1을 가리킵니다. 그리고 p가 가리키는 주소에 0x41424344를 입력했습니다. 이 값은 char로 치환하면 ABCD입니다. 우선 코드블럭의 결과를 봅니다. ----- 61fe17 <- c1의 값이 존재하는 메모리의 주소입니다. 61fe16 <- c2의 주소 61fe15 <- c3의 주소 61fe14 <- c4의 주소 D <-c1의 값입니다. <-c2의 값입니다. 문자열 끝을 나타내는 값이라, 글자가 표시되지 않습니다. <-c3의 값입니다. <-c4의 값입니다. ----- 주목할 부분은 주소의 값이 1씩 바뀌는 부분입니다. 메모리 상에서 char 변수들이 각 1byte씩 차지합니다. 다만 순서는 c4, c3, c2, c1이군요. 이 다음 p는 c1을 가리키도록 하고, ABCD를 입력했습니다. int인데 어떻게 ABCD냐 하면, 각 1byte씩 적절한 숫자를 입력했다는 정도로만 이해해 주세요... ABCD를 입력했지만, 실제로 메모리에 저장되는 순서는 반대이고, DCBA 순서대로 입력되어, c1에는 D가 입력됩니다. CBA는 그 다음 할당받지 않은 메모리에 입력되었습니다. 운 좋게 에러는 발생하지 않았군요. 다음 댓글에 제 결과를 쓰겠습니다. | 21.12.26 01:11 | |
(IP보기클릭)220.117.***.***
제 gcc의 결과는 이렇습니다. ----- 1b335bf4 1b335bf5 1b335bf6 1b335bf7 D C B A ----- 출력된 내용은 아까와 같이 char 변수들의 주소와 입력된 값입니다. 주목할 부분은, 아까와 같이 char 변수들의 주소가 1씩 차이나지만, 순서는 반대라는 것입니다. 이 경우 메모리에는 c1, c2, c3, c4 순으로 1byte씩 차지합니다. 이 다음에 p는 c1을 가리키고 ABCD를 입력했습니다. 이 경우도 메모리에는 DCBA 순으로 입력됩니다. 그 결과 c1에는 D, c2에는 C, c3에는 B, c4에는 A가 입력되었습니다. 저는 c2 c3 c4는 0으로 초기화를 했지만, p가 가리키는 위치, 즉 c1을 수정했는데 c2 c3 c4도 바뀌어버렸습니다. 이와 같이, int*에 char*를 지정하여도 int*는 메모리 상의 4byte를 건드리게 되며, 이게 정상동작할지 아닐지는 알 수 없습니다. | 21.12.26 01:18 | |
(IP보기클릭)59.16.***.***
int가 4byte니까 1byte 씩 끊어 읽을때 각각 65,66,67,68이 나오도록 4byte에 맞춰 숫자를 입력하셨다는 의미로 이해했습니다. | 21.12.26 01:19 | |
(IP보기클릭)59.16.***.***
아하.... union에서 char하고 int하고 설정했을때 값이 막 중구난방으로 바뀌는 경우와 비슷한 거 같네요. 늦은 밤에 이렇게 장문의 답변을 달아주시고T..T 죄송합니다. | 21.12.26 01:22 | |
(IP보기클릭)220.117.***.***
union도 마찬가지로, 결국 자기가 할당한 메모리를 int로 쓰느냐? char로 쓰느냐? 그건 자기가 코드를 짜기 나름입니다. 다만 union은 적어도 그 안에서는 할당된 메모리를 사용합니다. 그런데 calloc에서 1byte를 할당해서 그 주소를 받았는데, 나는 그 주소에 4byte를 억지로 쓰겠다? C라면 그렇게 할 수 있습니다. 다만 무슨 문제가 생길지 모르고, 위와 같이 다른 변수들을 모르는 사이에 수정해버릴 수도 있습니다. 실제로도 코드가 복잡해지면 내가 받은 포인터가 뭔지도 모르고 건드리다 에러가 나는 경우가 허다합니다. 결론적으로는, 코드가 동작하는 것 처럼 보여도 잘못된 코드일 수 있다는 점은 알아두세요. | 21.12.26 01:38 | |
(IP보기클릭)220.117.***.***
여기까지 쓴 김에 한가지 더 씁니다. int main() { char c1 = 0x00; *(int*)&c1 = 0x41424344; // ABCD printf("c1 value: %c\n", c1); char c2; char c3; char c4; printf("c2 value: %c\n", c2); printf("c3 value: %c\n", c3); printf("c4 value: %c\n", c4); return 0; } 코드를 잘 보시면, c1을 선언하고 c1에 ABCD를 아까처럼 대입하고, 그 다음에 c2, c3, c4를 선언하였습니다. 결과는 아래와 같습니다. c1 value: D <- 이때, 아직 c2, c3, c4는 존재하지 않습니다. c2 value: C c3 value: B c4 value: A 놀랍게도, 있어선 안될 C B A 값이 이미 c2 c3 c4에 입력되어 있습니다. 보시다시피 c2 c3 c4는 선언하고 바로 printf로 출력하고 있습니다. 이것 또한 쓰레기 값입니다. c2가 만들어지기 전에 이미 메모리는 사용된 상태이고, '우연히' C라는 값이 입력된 위치에 c2가 메모리를 할당받은 것입니다. 이와 같이, 할당한 메모리 보다 더 큰 영역에 값을 쓰는 것은 잘 되는 것 처럼 보일수도 있으나, 분명히 잘못 쓴 코드입니다. | 21.12.26 02:02 | |