다른 유형으로 한 유형의 이동 값이 엄격한 별칭을 위반합니까?

StackOverflow https://stackoverflow.com/questions/1926282

  •  20-09-2019
  •  | 
  •  

문제

UINT32_T를 사용하여 모든 유형의 항목을 이동시키기 위해 엄격한 별칭 규칙을 위반 한 다음 다시 읽습니까? 그렇다면 UINT32_T의 배열에서 모든 유형의 배열로 Memcpy에 대한 엄격한 별칭 규칙을 위반 한 다음 요소를 다시 읽습니까?

다음 코드 샘플은 두 경우를 모두 보여줍니다.

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(void) {
    const char *strings[5] = {
        "zero", "one", "two", "three", "four"
    };
    uint32_t buffer[5];
    int i;

    assert(sizeof(const char*) == sizeof(uint32_t));

    memcpy(buffer, strings, sizeof(buffer));

    //twiddle with the buffer a bit
    buffer[0] = buffer[3];
    buffer[2] = buffer[4];
    buffer[3] = buffer[1];

    //Does this violate strict aliasing?
    const char **buffer_cc = (const char**)buffer;
    printf("Test 1:\n");
    for (i=0; i<5; i++)
        printf("\t%s ", buffer_cc[i]);
    printf("\n");

    //How about this?
    memcpy(strings, buffer, sizeof(strings));
    printf("Test 2:\n");
    for (i=0; i<5; i++)
        printf("\t%s ", strings[i]);
    printf("\n");

    return 0;
}

32 비트 플랫폼에 대한 내 가정을 무시하십시오. 또한 요소가 uint32_t와 같은 크기가 아닌 경우, UINT32_T의 올바른 수를 패드하고 복사하는 것을 알고 있습니다. 내 질문은 그렇게하는 것이 엄격한 별칭을 위반하는지 여부에 중점을 둡니다.

도움이 되었습니까?

해결책

첫 번째 루프 하다 기술적으로 엄격한 별칭을 위반합니다 uint32_t 유형의 lValue를 통해 물체 char *. 그러나이 특정 사례에서 어떤 최적화가 어떤 문제를 일으킬 수 있는지 알기가 어렵습니다. 당신이 그것을 조금 변경했다면 당신은 다음과 같은 일을하고있었습니다.

printf("\t%s ", buffer_cc[0]);
buffer[0] = buffer[3];
printf("\t%s ", buffer_cc[0]);

~할 것 같다 두 번 인쇄 된 동일한 문자열을 참조 - 최적화기는로드 만 권한 내에 있으므로 buffer_cc[0] 두 번째 줄은 유형의 객체 만 수정하기 때문에 한 번 레지스터로 uint32_t.

두 번째 루프 memcpy다시 돌아와서 괜찮습니다.

다른 팁

buffer_cc[0] 그리고 strings[3] (예를 들어)는 동일한 메모리 위치를 참조하는 포인터이지만 동일한 유형이므로 엄격한 별칭을 위반하지 않습니다. buffer[0] 포인터가 아니므로 엄격한 별칭을 위반하지 않습니다. 앨리어싱 최적화는 포인터를 해독 할 때 발생하므로 문제가 발생할 것으로 기대하지 않습니다.

코드와 마지막 단락에서 알 수 있듯이 샘플 코드의 실제 문제는 포인터와 UINT32_T가 크기가 다를 때 발생합니다.

또한 항상 별명 a char* 엄격한 별칭을 위반하지 않고 다른 유형을 가리키는 것은 아니지만 그 반대는 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top