2014-10-24 3 views
0

저는 this question에서 왔는데 여기서 0-16 (각 4 비트) 사이에 있어야하는 단일 바이트에 2 개의 정수를 쓰려고했습니다. 지금은 파일을 닫고, 읽고 다른 프로그램을 실행하면이진 파일 쓰기 후 음수를 읽습니다

.... 문제는

for (int i = 0; i < 2; ++i) 
{ 
    char byteToRead; 
    file.seekg(i, std::ios::beg); 
    file.read(&byteToRead, sizeof(char)); 
    bool correct = file.bad(); 
    unsigned int num1 = (byteToRead >> 4); 
    unsigned int num2 = (byteToRead & 0x0F); 
} 

때때로이 다른 시간 나는 첫 번째 숫자는 부정적인 나와서 데에 불과 작동 두 번째 숫자는 항상 10 또는 9와 같은 것이고 내가 쓴 숫자가 가장 확실한 것은 아닙니다!

예를 들어, 처음 두 숫자는 작동하지만 다음 숫자는 작동하지 않습니다. examplem를 들어, 위의 읽을의 출력은 다음과 같습니다 바이트 1에서

At byte 0, num1 = 5 and num2 = 6 
At byte 1, num1 = 4294967289 and num2 = 12 

, NUM1 그것은 12 잘 쓰기 만 9 < < 4가 작동하지 않는 것 같다 (9)을해야한다. 내 끝에있는 byteToWrite는 byteToWrite -100 'œ'' 입니다. 나는 비슷한 문제가있는 this question을 체크 아웃했는데, 내 엔디안이 바로 여기있는 것처럼 느껴집니다.

+1

을 예컨대 캐스트 (또는 별칭) byteToReadunsigned char을 할 수있다. –

+0

오타가 질문 작성시 감사합니다. – user99999991

+0

시프트 할 때 부호 확장을 피하기 위해 부호없는 숫자를 사용하는 것이 좋습니다. –

답변

1

오른쪽 시프트 연산자는 가장 왼쪽 비트의 값을 보존합니다. 시프트 전에 가장 왼쪽의 비트가 0이면 시프트 후에도 0이됩니다. 1이면 교대 후에도 1이됩니다. 이것은 값의 부호를 보존 할 수있게합니다.

귀하의 경우에는 9 (0b1001)을 12 (0b1100)로 결합하므로 0b10011100 (0x9C)으로 작성하십시오. 비트 # 7은 1입니다.

byteToRead를 오른쪽으로 시프트하면 0b11111001 (0xF9)이되지만 암시 적으로 int로 변환됩니다. char에서 int 로의 변환도 값의 부호를 유지하므로 0xFFFFFFF9를 생성합니다. 그런 다음 암시 적 int는 암시 적으로 부호없는 int로 변환됩니다. 그래서 NUM1는이 개 솔루션이 4294967289.

입니다 0xFFFFFFF9 포함

  • 캐스트가 오른쪽 시프트를하고 서명 숯불에 byteToRead는;
  • 원하는 4 비트 만 유지하기 위해 이동 결과에 마스크를 적용하십시오.
+0

char에서 int 로의 변환은 오른쪽 시프트 이전에 발생합니다 –

1

이 문제의 원인은 byteToRead >> 4입니다. C에서 모든 산술 연산은 적어도 int 정밀도로 수행됩니다. 따라서 가장 먼저 일어나는 일은 byteToRead이 int로 승격된다는 것입니다.

이러한 프로모션은 가치 보존 형입니다. 귀하의 시스템은 보통 이며, 범위는 -128부터 127까지입니다. 문자가 처음에 -112 (비트 패턴 10010000)이었고 int로 승격 된 후 -112 (비트 패턴 11111...1110010000)의 값을 유지합니다.

음수 값의 오른쪽 시프트는 구현 정의이지만 일반적인 구현은 "산술 시프트"를 수행하는 것입니다. 즉 2로 나눗셈을 수행하는 것입니다. 결과적으로 byteToRead >> 4-7 (비트 패턴 11111....111001)이됩니다.산술 부호는 개조 UINT_MAX+1 주위에 배치로 정의되므로

, 4,295,967,289이고 UINT_MAX - 6-7unsigned int 결과로 변환.


이 문제를 해결하려면 산술을 수행하기 전에 부호없는 (unsigned) 코드로 변환해야합니다. 당신은 : 당신은 byteToRead``로 읽는하지만 myNums``의 번호를 구축하고

unsigned char byteToRead; 
file.read((char *)&byteToRead, 1);