2012-06-18 2 views
7

나는 오른쪽 아래에 등치 (=)만으로 후치 증가 (OR 사전 증가)가 가능하다는 인상을 받았다. 그러나 코드 조각 아래에서 컴파일 할 수 있습니다. 특히이 코드를 이해하는 데 도움을 줄 수 있습니까? 출처 : http://www.ibm.com/developerworks/library/pa-dalign/왼쪽에서 후속 증가

*data8++ = -*data8; 


void Munge8(void *data, uint32_t size) { 
    uint8_t *data8 = (uint8_t*) data; 
    uint8_t *data8End = data8 + size; 

    while(data8 != data8End) { 
     *data8++ = -*data8; 
    } 
} 
+0

지정'- * data8''* data8' 후 증가'에 data8' - 효과적으로'size' 바이트 data' – Erik

답변

3

인상이 잘못된 것 같아요. 다음과 같이 확실히 할 수 있습니다.

*a++ = *b++; 

실제로 이것은 종종 strcpy의 구현 방법입니다. 당신은 전혀 =없이 포스트 또는 사전 단위를 가질 수 있습니다 : 후행 증가가 할당 연산자의 왼쪽에 할 수없는 이유를 이유가

a++; 
+0

대기'에서, 그래서 계약에 있었다 부정 원래 게시물. 이것이 정의되지 않은 행동은 무엇입니까? –

+0

strcpy는 그렇게 구현되지 않습니다. 문자열의 끝을 큰 데이터 덩어리의 비트 패턴으로 먼저 찾은 다음 큰 덩어리 (일반적으로 64 비트)로 데이터를 복사합니다. –

+0

@sharth : 어떻게 정의되지 않습니까? 나는 표준 중독자가 아니지만 RHS를 먼저 평가 한 다음 LHS를 평가해야합니다. 따라서 문제가 없어야합니다. –

1

없습니다. 사후 증가 연산자는 이전 상태의 객체의 임시 복사본을 반환하고 임시 객체 (이 경우 포인터)는 객체에서 수행 된 연산을 가질 수 있습니다. 이제

의 경우 : 때문에 조작 순서의

*data8++ = -*data8; 

data8 포인터 먼저 이전 포인터 값의 복사본을 반환, 후 증가 될 것입니다. 이전 포인터 값은 역 참조되고 할당 연산자의 오른쪽에있는 표현식의 결과가 지정됩니다.

편집 : 다른 사람이 지적으로, 한 번 시퀀스 포인트없이 그 메모리 위치에 쓰는 동안보다 더 읽어 data8의 내용을 수정하고, 그래서 이것은 정의되지 않은 동작입니다.

+0

어떻게 정의되지 않습니까? 'x = -x'가 정의되지 않았다고 주장하는 것과 같습니다. –

+0

'data8'의 내용 (즉, 포인터 값 자체)을 수정하고 시퀀스 포인트가없는 두 개의 다른 위치에서 다시 읽습니다. 다른 사람들이 지적했듯이, LHS 또는 RHS가 먼저 평가되는 경우 두 가지 결과를 얻을 수 있습니다. C 표준은 어느면이 먼저 평가되어야하는지 정의하지 않기 때문에 "정의되지 않은 동작"입니다. 예를 들어, LHS와 RHS의 평가는 인터리브 될 수 있습니다!당신의 예제에서, LHS가'x'의 값을 읽지 않기 때문에 명확한 평가 순서가 있습니다, 단지 그것에 쓰는 것입니다. 따라서 읽기/쓰기는 하나뿐입니다. – Jason

+0

예. 나는 변명의 수면 부족을 주장 할 것이다. –

2

++data8이 가리키는 값이 아니라 포인터에 적용됩니다.

*data8 = -*data8; 
data8++; 

편집 :

*data8++ = -*data8;

가와 동등한 C99 standard 6.5Annex C을 읽은 후
, 그것은 =는 시퀀스 포인트 아니다 분명하다. 표준에는 &&, ||, ,? 만 언급되어 있습니다.

data8 더 시퀀스 포인트와 표준 RHS 먼저 평가해야 또는 좌가 먼저 평가해야하는지 여부를 의무화하지 않습니다 =의 양면에 수정되고 있기 때문에, 나는이 정의되지 않은 동작입니다 확신합니다.

Any good reason why assignment operator isn't a sequence point?

이 위의 게시물을 =하지 시퀀스 포인트되는 꽤 여기에 관련되어 설명합니다.

+0

'data8'은 대입 연산자의 양쪽에서 수정되지 않고 LHS에서 수정되지만, 쓰기에 대해 읽기의 순서가 결정되는 순서 포인트가 없으면 두 번 읽습니다. – Jason

+0

@ Jason 당신 말이 맞습니다. '= '시퀀스 포인트가 아닐 경우 여기에 키가 있습니다. –

7

이렇게 나는 이것이 정의되지 않은 동작이라는 것을 확신합니다.의 마지막 세미콜론 이외의 순서 포인트가 없습니다 :

*(0x20) = -*(0x20); 

또는

*(0x20) = -*(0x24); 

이 더 있기 때문에 : 내지 data8이가 0x20 같은 경우

*data8++ = -*data8; 

는,이 같다 (인터리브 시퀀스 포인트없이 두 번 읽는 동안 변수를 편집했기 때문에) 이것은 의 정의되지 않은 동작입니다.


다음 코드의 내용에 대해 이야기 할 수 있습니다. 위의 코드가 의도 한 바가 있습니다.

while(data8 != data8End) { 
    *data8 = -*data8; 
    data8++; 
} 

여기서 뭘하고있는 것이 더 쉽습니다. 입력 배열을 가져다가 8 비트 숫자로 된 배열을 보았습니다. 그런 다음, 제자리에서, 당신은 각각을 부정합니다.

+0

"변수"를 혼동스럽게 생각합니다. 포인터의 값과 값에 의해 주소 포인터에 저장된 값은 두 가지입니다. 이 경우에는 변수를 두 번 읽는 동안 아무도 편집하지 않았습니다. "data8"에 의한 주소 포인터의 값은 RHS에서 한번 읽혀집니다. 그것은 한 번 쓰여집니다. 포인터는 LHS에서 한 번 변경됩니다. –

+0

아니면 내가 할 수도 있습니다. Hehe –

+2

@Vlad,'='는 시퀀스 포인트가 아닙니다. –

0

내가 생각

* 내지 data8 ++ = - * 내지 data8;

* 내지 data8 동등 = - * (내지 data8 + 1);

내지 data8 = 내지 data8 한