C ++ ‘for’루프에 두 개의 증분 문을 어떻게 넣습니까? 같습니다. for (int i = 0; i !=

for하나가 아닌 루프 조건 에서 두 개의 변수를 증가시키고 싶습니다 .

그래서 다음과 같습니다.

for (int i = 0; i != 5; ++i and ++j)
    do_something(i, j);

이것에 대한 구문은 무엇입니까?



답변

일반적인 관용구는 두 피연산자를 모두 평가하고 두 번째 피연산자를 반환하는 쉼표 연산자 를 사용하는 것 입니다. 그러므로:

for(int i = 0; i != 5; ++i,++j)
    do_something(i,j);

하지만 정말 쉼표 연산자입니까?

이제 그 글을 쓴 어떤 주석가는 그것이 실제로 쉼표 연산자가 아니라 for 문에있는 특별한 구문 설탕이라고 제안했습니다. GCC에서 다음과 같이 확인했습니다.

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

x가 a의 원래 값을 가져 오기를 기대했기 때문에 x에 대해 5,6,7 ..이 표시되어야합니다. 내가 얻은 것은

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

그러나 구문 분석기가 실제로 쉼표 연산자를 보도록하기 위해 표현식을 괄호로 묶으면

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

처음에는 이것이 쉼표 연산자로 작동하지 않는다는 것을 보여 주었다고 생각했지만, 이것은 단순히 우선 순위 문제입니다. 쉼표 연산자는 가능한 가장 낮은 우선 순위 를 가지므로 x = i ++, a ++ 표현식은 효과적으로 (x = i ++), a ++로 구문 분석 됨

모든 의견을 보내 주셔서 감사합니다. 흥미로운 학습 경험이었고 저는 수년 동안 C를 사용해 왔습니다!


답변

이 시도

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);


답변

하지 마십시오!

에서 http://www.research.att.com/~bs/JSF-AV-rules.pdf :

AV 규칙 199
for 루프의 증분 표현식은 단일 루프 매개 변수를 루프의 다음 값으로 변경하는 것 외에 다른 작업을 수행하지 않습니다.

근거 : 가독성.


답변

for (int i = 0; i != 5; ++i, ++j)
    do_something(i, j);


답변

저는 FOR 루프의 증분 절에 두 번째 인덱스를 코딩하는 방법을 상기하기 위해 여기에 왔습니다. 주로 C ++로 작성된 다른 프로젝트에 통합 한 샘플에서이를 관찰하여 수행 할 수 있다는 것을 알고있었습니다.

오늘 저는 C #으로 작업하고 있지만 FOR 문은 모든 프로그래밍에서 가장 오래된 제어 구조 중 하나이기 때문에 이와 관련하여 동일한 규칙을 따를 것이라고 확신했습니다. 고맙게도 저는 최근에 이전 C 프로그램 중 하나에서 FOR 루프의 동작을 정확하게 문서화하는 데 며칠을 보냈으며 그 연구에서 오늘날의 C # 문제, 특히 두 번째 인덱스 변수의 동작에 적용되는 교훈이 있다는 것을 금방 깨달았습니다. .

다음은 내 관찰에 대한 요약입니다. 오늘 내가 본 모든 일은 Locals 창에서 변수를주의 깊게 관찰함으로써 C # FOR 문이 C 또는 C ++ FOR 문과 똑같이 작동한다는 내 기대를 확인했습니다.

  1. FOR 루프가 처음 실행될 때 증분 절 (3 개 중 3 번째 절)을 건너 뜁니다. Visual C 및 C ++에서 증분은 루프를 구현하는 블록 중간에 3 개의 기계 명령어로 생성되므로 초기 단계에서 초기화 코드를 한 번만 실행 한 다음 증분 블록을 건너 뛰어 종료 테스트를 실행합니다. 이것은 인덱스 및 제한 변수의 상태에 따라 FOR 루프가 0 회 이상 실행되는 기능을 구현합니다.
  2. 루프 본문이 실행되는 경우 마지막 문은 첫 번째 반복에서 건너 뛴 세 개의 증가 명령 중 첫 번째로 점프하는 것입니다. 이러한 실행 후 제어는 중간 절을 구현하는 제한 테스트 코드로 자연스럽게 떨어집니다. 해당 테스트의 결과는 FOR 루프의 본문이 실행되는지 또는 제어가 해당 범위의 맨 아래에있는 점프를지나 다음 명령어로 전송되는지 여부를 결정합니다.
  3. 제어는 FOR 루프 블록의 맨 아래에서 증가 블록으로 전송되기 때문에 테스트가 실행되기 전에 인덱스 변수가 증가합니다. 이 동작은 학습 한 방식으로 제한 절을 코딩해야하는 이유를 설명 할뿐만 아니라 쉼표 연산자를 통해 추가하는 보조 증분에 영향을줍니다. 이는 세 번째 절의 일부가되기 때문입니다. 따라서 첫 번째 반복에서 변경되지 않고 본문을 실행하지 않는 마지막 반복에서 변경됩니다.

루프가 끝날 때 인덱스 변수 중 하나가 범위에 남아 있으면 해당 값은 실제 인덱스 변수의 경우 루프를 중지하는 임계 값보다 하나 더 높습니다. 마찬가지로, 예를 들어 두 번째 변수가 루프에 들어가기 전에 0으로 초기화되면 마지막 값은 감소가 아닌 증가 (++)이고 루프의 본문은 값을 변경합니다.


답변

나는 squelart에 동의합니다. 두 변수를 증가시키는 것은 버그가 발생하기 쉬우 며 특히 그중 하나만 테스트하는 경우 더욱 그렇습니다.

다음은이를 수행하는 읽기 쉬운 방법입니다.

int j = 0;
for(int i = 0; i < 5; ++i) {
    do_something(i, j);
    ++j;
}

For루프는 하나의 증가 / 감소 변수에서 루프가 실행되는 경우를 의미합니다. 다른 변수의 경우 루프에서 변경하십시오.

j연결 해야하는 경우 i원래 변수를 그대로두고 추가하지 않는 이유는 i무엇입니까?

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

논리가 더 복잡한 경우 (예를 들어 실제로 둘 이상의 변수를 모니터링해야 함) while루프를 사용합니다 .


답변

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    }
}