귀하의 질문은 아마도 "왜 이러한 구조가 C에서 정의되지 않은 동작입니까?" 귀하의 질문은 아마도 "이 코드 ()를 사용하여 ++
예상 한 값을 얻지 못한 이유는 무엇 입니까?"였으며 누군가 귀하의 질문을 중복으로 표시하여 여기로 보냈습니다.
이 답변은 그 질문에 답하려고합니다 : 왜 당신의 코드가 당신에게 기대 한 대답을주지 않았으며, 예상대로 작동하지 않을 표현을 인식하고 피하는 법을 배울 수 있습니다.
나는 지금까지 C ++
와 --
연산자 의 기본 정의를 듣고 접두사 형식 ++x
이 postfix 형식 과 어떻게 다른지 들었습니다 x++
. 그러나 이러한 연산자는 생각하기가 어렵습니다. 이해를 돕기 위해 아마도 다음과 같은 작은 테스트 프로그램을 작성했을 것입니다.
int x = 5;
printf("%d %d %d\n", x, ++x, x++);
그러나 놀랍게도이 프로그램은 당신이 이해하는 데 도움 이 되지 않았습니다. 이상하고, 예상치 못한, 설명 할 수없는 결과물을 인쇄 ++
했습니다.
또는 아마도 이해하기 어려운 표현을보고있을 것입니다
int x = 5;
x = x++ + ++x;
printf("%d\n", x);
아마도 누군가 당신에게 그 코드를 퍼즐로 줬을 것입니다. 이 코드는 또한 특히 코드를 실행하는 경우 의미가 없으며 두 개의 다른 컴파일러에서 컴파일하고 실행하면 두 가지 다른 응답을 얻을 수 있습니다! 무슨 일이야? 어떤 대답이 맞습니까? (그리고 대답은 둘 다 또는 둘 다 없다는 것입니다.)
지금까지 들었 듯이,이 모든 표현들은 정의 되어 있지 않습니다 . 즉, C 언어는 그들이 할 일을 보증하지 않습니다. 컴파일하고 실행하는 한 작성할 수있는 모든 프로그램이 고유하고 잘 정의 된 출력을 생성 할 것이라고 생각했기 때문에 이것은 이상하고 놀라운 결과입니다. 그러나 정의되지 않은 동작의 경우에는 그렇지 않습니다.
식이 정의되지 않은 이유는 무엇입니까? 관련된 표현이 있습니까++
와--
항상 정의되지 않습니까? 물론 아닙니다 : 이들은 유용한 연산자이며 제대로 사용하면 완벽하게 정의됩니다.
우리가 표현에 대해 정의하지 않은 표현은 한 번에 너무 많은 일이 발생하는 경우, 어떤 일이 일어날 지 확실하지 않지만 결과가 중요한 순서 일 때입니다.
이 답변에서 사용한 두 가지 예로 돌아가 보겠습니다. 내가 쓸 때
printf("%d %d %d\n", x, ++x, x++);
문제는, 호출하기 전에되고 printf
, 컴파일러의 값을 계산 않습니다 x
첫째, 나 x++
, 아니면 ++x
? 그러나 우리는 모른다 . C에는 함수에 대한 인수가 왼쪽에서 오른쪽으로, 오른쪽에서 왼쪽으로 또는 다른 순서로 평가된다는 규칙이 없습니다. 우리는 컴파일러가 할 것입니다 여부를 말할 수 없다 그래서 x
첫째, 다음 ++x
, 다음 x++
, 또는 x++
다음 ++x
다음 x
, 또는 다른 순서. 그러나 순서는 분명히 중요합니다. 컴파일러가 사용하는 순서에 따라 다른 결과가 명확하게 인쇄되기 때문입니다.printf
입니다.
이 미친 표현은 어떻습니까?
x = x++ + ++x;
이 표현의 문제는 x의 값 수정할 수있는 세 가지 다른 시도 포함되어있다 : (1) x++
부분의 시도는, X 1 추가에 새 값을 저장하기 위해 x
, 그리고 이전 값을 반환을 x
; (2) ++x
부품이 x에 1을 더하고에 새 값을 저장하고 새 값을 x
반환 하려고합니다 x
. 그리고 (3) x =
파트는 다른 두 개의 합계를 다시 x에 할당하려고 시도합니다. 이 세 번의 과제 중 어느 것이 "승리"할 것인가? 세 값 중 어느 것이 실제로 할당 x
됩니까? 다시 말하지만 놀랍게도 C에는 우리에게 말할 규칙이 없습니다.
우선 순위 또는 연관성 또는 왼쪽에서 오른쪽으로 평가하면 어떤 순서로 발생하는지 알 수 있지만 그렇지 않습니다. 당신은 저를 믿지 않을 수도 있지만, 제 말을 들어주세요. 다시 말하겠습니다 : 우선 순위와 연관성은 C에서 표현식의 평가 순서의 모든 측면을 결정하지 않습니다. 특히, 하나의 표현식 내에 여러 개가 있다면 x
, 우선 순위 및 연관성에 새로운 값을 할당하려고 시도하는 다른 지점 은 이러한 시도 중 어느 것이 처음 또는 마지막으로 발생하는지 또는 다른 것을 알려주지 않습니다 .
따라서 모든 배경과 소개를 벗어난 상태에서 모든 프로그램이 잘 정의되어 있고 어떤 표현을 작성할 수 있고 어떤 표현을 쓸 수 없는지 확인하려면 어떻게해야합니까?
이 표현들은 모두 괜찮습니다.
y = x++;
z = x++ + y++;
x = x + 1;
x = a[i++];
x = a[i++] + b[j++];
x[i++] = a[j++] + b[k++];
x = *p++;
x = *p++ + *q++;
이 표현식은 모두 정의되어 있지 않습니다.
x = x++;
x = x++ + ++x;
y = x + x++;
a[i] = i++;
a[i++] = i;
printf("%d %d %d\n", x, ++x, x++);
마지막 질문은 어떤식이 잘 정의되어 있고 어떤식이 정의되어 있지 않은지 어떻게 알 수 있습니까?
앞에서 말했듯이 정의되지 않은 표현식은 한 번에 너무 많은 일이 발생하는 순서, 무슨 일이 발생했는지, 순서가 중요한 부분을 나타내는 표현입니다.
- 둘 이상의 다른 위치에서 수정 (할당)되는 변수가 하나 있으면 어떤 수정이 먼저 발생하는지 어떻게 알 수 있습니까?
- 한 곳에서 수정되고 다른 곳에서 값을 사용하는 변수가있는 경우 이전 값을 사용하는지 새 값을 사용하는지 어떻게 알 수 있습니까?
식에서 # 1의 예로서
x = x++ + ++x;
`x를 수정하려는 세 가지 시도가 있습니다.
# 2의 예로서, 표현에서
y = x + x++;
우리는 모두의 값을 사용 x
하고 수정합니다.
이것이 바로 답입니다. 작성한 표현식에서 각 변수는 최대 한 번 수정되고 변수가 수정 된 경우 해당 변수의 값을 다른 곳에서도 사용하려고 시도하지 마십시오.