C입문생 님이 쓰신 글 :
: #include <stdio.g>
:
: int main(void)
: {
: char a,b,result;
:
: printf("-50과 +50사이의 값을 입력하시오");
: scanf("%d %d",&a,&b);
:
: result=a+b;
: printf("a+b=%d",result);
:
: return 0;
: }
: 이렇게 하고서
: 실행한 후에 두개의 값을 넣으면 예를 들어 5와 7을 입력하면
: 0+7=7 이렇게 나와요...
: 5가 왜 입력이 안되는지 거 참;;
: char을 int로 바꾸면 정상적으로 되는데
: 제가 열혈강의책으로 공부중인데(초보) 그중에 있는 예제이거든요...
: char 은 변수를 하나밖에 선언 못하는건 가요? 책이 잘못된건가요?
: 선배님들의 조언 부탁드립니다. (__) 꾸벅.
이 문제는 생각보다 복잡합니다.
a와 b는 함수 내의 비정적변수이므로 스택에 생성이 되는데, 제시하신 코드에서 a와 b는 연속된 공간에 생성됩니다.
scanf 함수의 포맷 문자열 내의 %d는 정수를 입력받으라는 뜻으로서 저장공간(메모리,변수)도 당연히 sizeof(int) 크기라고 scanf 함수가 생각합니다.
그런데, 실제 전달한 것은 char 형 변수의 주소이므로 아래와 같이 문제가 발생할 수 있습니다.
두 가지로 나누어 말씀드리겠습니다.
1. a의 번지가 b의 번지보다 높은 경우
a와 b는 char 형이고 연속된 공간에 생성되므로, a를 10번지라 하면 b는 9번지가 됩니다.
이 때 scanf("%d %d",&a,&b);하면 scanf 함수에 a의 번지와 b의 번지가 전달되며
scanf 함수 안에서는 포맷 문자열에 있는
첫번째 %d를 만나면, 전달받은 a의 번지(&a)를 int*로 해석하고 10번지에서 시작하여 sizeof(int) 바이트(보통 4바이트)에 해당하는 메모리에 사용자가 입력한 값(5)을 저장합니다.
5는 1바이트에 저장가능하므로 최하위 바이트인 10번지에 5가 기록되고 11~13번지에는 0이 기록됩니다.
두 번째 %d를 만나면, 전달받은 b의 번지(&b)를 int*로 해석하고 9번지에서 시작하여 sizeof(int) 바이트(보통 4바이트)에 해당하는 메모리에 사용자가 입력한 값(7)을 저장합니다.
7은 1바이트에 저장가능하므로 최하위 바이트인 9번지에 7이 기록되고 10~12번지에는 0이 기록됩니다.
결과적으로, 9번지(b변수)에는 7이 저장되게 되고 10번지(a변수)에는 0이 저장되게 됩니다.
물론, 11~13번지의 메모리 침범이 발생했습니다.
2. a의 번지가 b의 번지보다 낮은(앞선) 경우
a와 b는 char 형이고 연속된 공간에 생성되므로, a를 10번지라 하면 b는 11번지가 됩니다.
이 때 scanf("%d %d",&a,&b);하면 scanf 함수에 a의 번지와 b의 번지가 전달되며
scanf 함수 안에서는 포맷 문자열에 있는
첫번째 %d를 만나면, 전달받은 a의 번지(&a)를 int*로 해석하고 10번지에서 시작하여 sizeof(int) 바이트(보통 4바이트)에 해당하는 메모리에 사용자가 입력한 값(5)을 저장합니다.
5는 1바이트에 저장가능하므로 최하위 바이트인 10번지에 5가 기록되고 11~13번지에는 0이 기록됩니다.
두 번째 %d를 만나면, 전달받은 b의 번지(&b)를 int*로 해석하고 11번지에서 시작하여 sizeof(int) 바이트(보통 4바이트)에 해당하는 메모리에 사용자가 입력한 값(7)을 저장합니다.
7은 1바이트에 저장가능하므로 최하위 바이트인 11번지에 7이 기록되고 12~14번지에는 0이 기록됩니다.
결과적으로, 10번지(a변수)에는 5가 저장되게 되고 11번지(b변수)에는 7이 저장되게 됩니다.
물론, 12~14번지의 메모리 침범이 발생했습니다.
결국, 문제를 해결하려면 a,b,result를 char가 아닌 int로 선언/정의하셔야 합니다.
|