문제

컴파일 타임에 비트 필드의 마스크를 찾는 이식 가능한 방법이 C에 있습니까?

이상적으로는 다음과 같이 필드를 원자적으로 지울 수 있기를 바랍니다.

struct Reference {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
};

struct Reference myRef;
__sync_and_and_fetch(&myRef, age, ~AGE_MASK);

그렇지 않으면 내가 원하는 것보다 더 무거운 구조체에 대한 잠금을 해제해야 합니다.

도움이 되었습니까?

해결책

또는 마스크를 정말로 원한다면 :

union Reference {
  unsigned asWord;
  struct {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
  } asFields;
}

Reference agemask_ref;
agemask_ref.asFields = (typeof(agemask_ref.asFields)){0, -1, -1};
unsigned agemask = agemask_ref.asWord;

다른 팁

당신은 다음과 같은 일을 할 수 있습니다.

union Reference {
  unsigned asWord;
  struct {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
  } asFields;
}

원자 적으로 MyRef의 필드를 명확하게하기 위해

union Reference myRef;

union Reference oldr = myRef;
union Reference newr = oldr;
newr.asFields.age = 0;
compare_and_swap(&myRef.asWord, oldr.asWord, newr.asWord);

(compare_and_swap이 실패 할 때 처리 할 수없는 코드)

나는 컴파일 시간에 그것을하는 방법을 모르겠지만, 런타임에 적절한 크기의 설계되지 않은 int가있는 비트 필드 구조물의 인스턴스를 조합하고 모든 필드를 0으로 설정하는 간단한 문제 여야합니다. 어느쪽으로 설정 해야하는지 관리하십시오. 서명되지 않은 int의 값은 원하는 비트 마스크입니다. 스타트 업에서 각 필드에 대해, 아마도 반복적 인 코드를 피하기 위해 매크로를 사용하여 할 수 있습니다. 충분하지 않습니까?

바이트 오프셋에 적용되지만 비트 필드에는 작동하지 않는 것 같습니다. 나는 열거/정의 (0x01 0x02 등)로 필드를 다시 고정하고 비트를 직접 관리하므로 원자 변화를 얻을 수 있습니다.

예, 가능합니다.값을 캡처하고 작업을 수행해야 합니다.그런 다음 메모리에 여전히 이전 값이 포함되어 있는 경우 원자 비교 및 ​​스왑(예: Windows의 InterlockedCompareExchange)을 사용하여 새 값을 저장해야 합니다.누군가 값을 수정한 경우 루프를 반복하여 다시 시도합니다.이는 내장 함수를 사용할 수 없는 단어 크기의 데이터에 대해 작업을 수행하기 위한 표준 패턴입니다.

아래 코드는 int를 사용합니다. Keith가 지적했듯이 공용체를 사용하여 구조체의 값을 int로 가져올 수 있습니다.

int oldValue, newValue;
do
{
    oldValue = myRef;
    newValue = oldValue & ~AGE_MASK;
} while (InterlockedCompareExchange(&myRef, newValue, oldValue) != oldValue);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top