모든 비트를 true로 설정하기 위해 -1을 사용하는 것이 안전합니까? // all bits are true 이것이

이 패턴이 C & C ++에서 많이 사용되는 것을 보았습니다.

unsigned int flags = -1;  // all bits are true

이것이 이것을 달성하기에 좋은 휴대용 방법입니까? 또는 사용 0xffffffff또는 ~0더 나은?



답변

가장 간단한 방법이므로 표시 한대로 정확하게 수행하는 것이 좋습니다. 실제 부호 표시와 상관없이 항상-1 작동하는 초기화를 수행 하고 올바른 피연산자 유형을 가져야하기 때문에 때로는 놀라운 동작을 수행합니다. 그래야만 유형의 가치가 가장 높아집니다 .~unsigned

가능한 놀람의 예를 보려면 다음을 고려하십시오.

unsigned long a = ~0u;

모든 비트가 1 인 패턴을 반드시 저장할 필요는 없습니다 a. 그러나 먼저의 비트 1이 모두 포함 된 패턴을 unsigned int만든 다음에 할당합니다 a. unsigned long더 많은 비트가 있을 때 발생 하는 것은 모든 비트가 1이 아니라는 것입니다.

그리고이 것을 고려하십시오. 이것은 2가 아닌 보수 표현에 실패합니다 :

unsigned int a = ~0; // Should have done ~0u !

그 이유는 ~0모든 비트를 뒤집어 야하기 때문입니다 . 반전 -1하면 2의 보수 기계 (필요한 값)에서 산출 되지만 다른 표현 에서는 산출 되지 않습니다-1 . 보완 기계에서는 0을 산출합니다. 따라서 사람의 보완 시스템에서 위의 값은 a0으로 초기화 됩니다.

이해해야 할 것은 비트가 아니라 값에 관한 것입니다. 변수는 값으로 초기화됩니다 . 초기화 프로그램에서 초기화에 사용 된 변수의 비트를 수정하면 해당 비트에 따라 값이 생성됩니다. a가능한 가장 높은 값 으로 초기화 하기 위해 필요한 값은 -1또는 UINT_MAX입니다. 두 번째는 유형에 따라 달라집니다.에 a사용해야 ULONG_MAX합니다 unsigned long. 그러나 첫 번째는 유형에 의존하지 않으며 가장 높은 가치를 얻는 좋은 방법입니다.

우리는 -1 는 모든 비트가 하나 인지 (항상 그렇지 않음)에 대해 이야기 하지 않습니다. 그리고 우리는 물론 모든 비트가 1 비트 인지 여부에 대해 이야기 하지 않습니다~0 .

그러나 우리가 이야기하고있는 것은 초기화 된 flags변수 의 결과입니다 . 그리고 그것을 위해서만-1 모든 유형과 기계 작동합니다.


답변

  • unsigned int flags = -1; 휴대용입니다.
  • unsigned int flags = ~0; 그것은 2의 보수 표현에 의존하기 때문에 이식성이 없습니다.
  • unsigned int flags = 0xffffffff; 32 비트 정수를 가정하기 때문에 이식성이 없습니다.

C 표준에서 보장하는 방식으로 모든 비트를 설정하려면 첫 번째 비트를 사용하십시오.


답변

솔직히 나는 모든 fff가 더 읽기 쉽다고 생각합니다. 반 패턴에 대한 의견에 관해서는, 모든 비트가 설정되고 지워지는 것을 정말로 염려한다면 어쨌든 변수의 크기에 관심이있는 상황에 있다고 주장 할 것입니다. :: uint16_t 등


답변

언급 된 문제를 피하는 방법은 간단하게 수행하는 것입니다.

unsigned int flags = 0;
flags = ~flags;

휴대가 편리합니다.


답변

플래그에 부호없는 int를 사용하는 것이 확실하지 않다는 것은 C ++의 첫 번째 장소입니다. 비트 셋 등은 어떻습니까?

std::numeric_limit<unsigned int>::max()0xffffffff부호없는 int가 32 비트 정수라고 가정 하기 때문에 더 좋습니다 .


답변

unsigned int flags = -1;  // all bits are true

“이것이 이것을 달성하는 좋은 [,] 휴대용 방법입니까?”

가지고 다닐 수 있는? .

좋은? 이 글타래에 표시된 모든 혼란에 의해 입증되는 논쟁의 여지가 있습니다. 동료 프로그래머가 혼동없이 코드를 이해할 수있을 정도로 명확하다는 것은 좋은 코드를 측정하는 차원 중 하나 여야합니다.

또한이 방법은 컴파일러 경고 가 발생하기 쉽습니다 . 컴파일러를 방해하지 않고 경고를 없애려면 명시 적 캐스트가 필요합니다. 예를 들어

unsigned int flags = static_cast<unsigned int>(-1);

명시 적 캐스트에서는 대상 유형에주의를 기울여야합니다. 대상 유형에주의를 기울이면 다른 접근 방식의 함정을 자연스럽게 피할 수 있습니다.

내 조언은 타겟 유형에주의를 기울이고 암시 적 변환이 없는지 확인하는 것입니다. 예를 들면 다음과 같습니다.

unsigned int flags1 = UINT_MAX;
unsigned int flags2 = ~static_cast<unsigned int>(0);
unsigned long flags3 = ULONG_MAX;
unsigned long flags4 = ~static_cast<unsigned long>(0);

모두 동료 프로그래머에게 정확하고 분명 합니다.

그리고 C ++ 11 을 사용 auto하면 다음 중 하나를 더 간단하게 만들 수 있습니다 .

auto flags1 = UINT_MAX;
auto flags2 = ~static_cast<unsigned int>(0);
auto flags3 = ULONG_MAX;
auto flags4 = ~static_cast<unsigned long>(0);

나는 단순히 올바른 것보다 정확하고 명백한 것으로 생각합니다.


답변

표준의해 -1을 부호없는 유형으로 변환하는 것은 모든 사람을 초래합니다. 유형이 ~0U있기 때문에 일반적으로 사용이 좋지 않으며 명시 적으로와 같은 것을 쓰지 않는 한 더 큰 부호없는 유형의 모든 비트를 채우지는 않습니다 . 제정신 시스템에서는 과 동일해야 하지만, 표준은 보완 및 부호 / 크기 표현을 허용하므로 엄격히 이식성이 없다.0unsigned int~0ULL~0-1

물론 0xffffffff정확히 32 비트가 필요하다는 것을 알고 있으면 글을 쓰는 것이 좋습니다 .하지만 -1은 여러 유형에서 작동하는 매크로와 같이 유형의 크기를 모르는 경우에도 모든 컨텍스트에서 작동한다는 이점이 있습니다 또는 구현에 따라 유형의 크기가 다른 경우 당신은 유형을 알고 있다면, 다른 안전한 방법은 모든 사람이 제한 매크로입니다 얻을 UINT_MAX, ULONG_MAX,ULLONG_MAX , 등

개인적으로 나는 항상 -1을 사용합니다. 그것은 항상 작동하며 그것에 대해 생각할 필요가 없습니다.