itsource

C에서 64비트 변수 선언

mycopycode 2023. 9. 24. 12:50
반응형

C에서 64비트 변수 선언

질문있습니다.

uint64_t var = 1; // this is 000000...00001 right?

내 암호대로라면 이렇게 될 겁니다

var ^ (1 << 43)

그러나 1이 64비트여야 한다는 것을 어떻게 알 수 있습니까?제가 대신 써야 하는 거 아닌가요?

var ^ ( (uint64_t) 1 << 43 )

하신 대로 1 입니다입니다.int에서 2의일 것입니다 에서 2은 32입니다).입니다 43고.1<<43 두 합니다 .실,실int됩니다.int뿐만 아니라.

그래도 C에서 부호화된 정수 오버플로는 정의되지 않은 동작이므로 원칙적으로 어떤 일도 일어날 수 있습니다.당신의 경우, 컴파일러가 64비트 레지스터에서 그 시프트를 수행하기 위해 코드를 내보냈을 것이고, 그래서 운 좋게도 그것은 작동하는 것처럼 보입니다. 보장되고 정확한 결과를 얻으려면 당신이 작성한 두 번째 양식을 사용하거나, 또는 대안적으로 다음을 지정해야 합니다.1unsigned long long 그대로e를 ullunsigned long long최소 64비트가 보장됩니다.

var ^ ( 1ULL << 43 )

OP의 의합니다는 합니다. 상수를 계산합니다.( (uint64_t) 1 << 43 )

OP의 작은 예의 경우, 아래 2개도 동일한 성능을 발휘할 가능성이 높습니다.

uint64_t var = 1; 
// OP solution)
var ^ ( (uint64_t) 1 << 43 )
// Others suggested answer
var ^ ( 1ULL << 43 )        

위의 결과는 은 같지만 유형은 다릅니다.잠재적인 차이는 C에 두 가지 유형이 존재하는 방식에 있습니다.uint64_t그리고.unsigned long long그리고 그 뒤에 일어날 일들.

uint64_t정확한 범위는 0에서 2-1입니다64.
unsigned long long범위가 0에서 최소64 2-1입니다.

한다면unsigned long long요즘 많은 기계에 있는 것처럼 보이기 때문에 항상 64비트가 될 것입니다. 하지만 미래를 내다보고 이 코드가 다음과 같은 기계에서 실행되었다고 합시다.unsigned long long16바이트(0에서 최소 2-1128)였습니다.

다음의 작위적인 예는 다음과 같습니다.의 첫 입니다.^uint64_t, 3이 됩니다.uint64_t, 모듈로 2를64 수행하면 오버플로우가 발생하면 결과가 다음에 할당됩니다.d1다음 의 ^입니다.unsigned long long그리고 3을 곱하면 제품은 2보다64 클 수 있고 그 다음에 할당됩니다.d2.그렇게d1그리고.d2대답이 다릅니다

double d1, d2;
d1 = 3*(var ^ ( (uint64_t) 1 << 43 ));
d2 = 3*(var ^ ( 1ULL << 43 ));

과 함께 ,unit64_t같이 .unit64_t그리고.unsigned long long같습니다.만약 당신의 대답이 a가 되는 것이 괜찮다면,unsigned long long제 요, 한다면, 의 타입을 요.uint64_t을 엉망으로 만드는 을 원하지 않습니다 .

var ^ ( 1ULL << 43 )해야 합니다.

휴대용으로 사용할 수 있는 방법.unit64_t일정한 것은 사용하는 것입니다.UINT64_C에서)stdint.h):

UINT64_C(1) << 43

아마도 그렇 것입니다UINT64_C(c)됩니다와 됩니다.c ## ULL.

C 표준부터:

.INTN_C(value)다에 .int_leastN_t.UINTN_C(value)다에 .uint_leastN_t를 들어 . , uint_least64_t입니다의 입니다.unsigned long long int,그리고나서UINT64_C(0x123)할 수 .0x123ULL.

당신의 컴파일러는 시프트가 64비트로 이루어져야 한다는 것을 모릅니다.그러나 이 특정 코드에 대한 이 특정 구성의 컴파일러의 이 특정 버전에서는 두 가지 오류가 발생합니다.그렇지 않을 거야.

를 가정하면int는 당신의 플랫폼에서 32비트 타입입니다. (아마도 매우 가능성이 높습니다.) 두가지 오류가 있습니다.1 << 43다음과 같습니다.

  • 시프트 양이 왼쪽 피연산자 유형의 너비보다 크거나 같으면 동작이 정의되지 않습니다.x입니다.int아니면unsigned int,그리고나서x << 43는되지 않은 .x << 32y.x << nn ≥ 32.예를들면1u << 43정의되지 않은 행동도 있을 겁니다
  • 왼쪽 피연산자에 서명된 유형이 있는데 작업 결과가 해당 유형에 오버플로되면 동작이 정의되지 않습니다.를 들면e0x12345 << 16다이기 되지 않은 .int다에 .int 에.0x12345u << 16다 .0x23450000u.

"정의되지 않은 동작"은 컴파일러가 잘못된 결과를 반환하거나 충돌하는 코드를 자유롭게 생성할 수 있음을 의미합니다.이 경우 원하는 결과를 얻을 수 있습니다. 하지만 머피의 법칙에 따르면 생성된 코드는 언젠가는 원하는 대로 실행되지 않습니다.

작업이 64비트 유형에서 수행되도록 하려면 왼쪽 피연산자가 64비트 유형인지 확인해야 합니다. 결과를 할당하는 변수 유형은 중요하지 않습니다.입니다와 문제입니다.float x = 1 / 2n을 초래하는x데 0.5닌 0합니다. 연산자의 동작을 결정하는 데는 피연산자의 유형만 중요합니다.아무 것이나(uint64)1 << 43아니면(long long)1 << 43아니면(unsigned long long)1 << 43아니면1ll << 43아니면1ull << 43다.서명된 유형을 사용하는 경우 오버플로가 없는 경우에만 동작이 정의되므로 오버플로 시 잘라낼 것으로 예상되는 경우 서명되지 않은 유형을 사용해야 합니다. 수 되지 않은 을 좋아하기 입니다).다. 만약 서명된 유형을 사용한다면 디버깅 목적으로 값을 출력하는 것만으로도 동작이 바뀔 수 있습니다. (컴파일러들은 정의되지 않은 동작을 이용하여 가장 효율적인 코드를 생성하는 것을 좋아하기 때문입니다. o마이크로 레벨. 레지스터 할당에 대한 압력과 같은 것에 매우 민감할 수 있습니다.

uint64_t모든 을 그 , 즉이 더 합니다.따라서:

uint64_t var = 1;
… var ^ ((uint64_t)1 << 43) …

언급URL : https://stackoverflow.com/questions/19451101/declaring-64-bit-variables-in-c

반응형