2016-08-16 7 views
1

C에서 입력 일련 번호를 기반으로 키를 생성하는 다음 코드가 있습니다.C# 대 C 오버플로 예외 문자의 비트 보수

unsigned int32 passkey(unsigned int32 snumber) 
{ 
    char snstring[11]; 
    unsigned int32 pwd; 
    int i = 0; 
    itoa(snumber,10,snstring); 
    do{ 
     snstring[i+1] -= '0'; 
     snstring[i] = ~snstring[i+1]; 
     snstring[i] &= 0x07; 
     i++; 
    }while(i < 9); 
    snstring[9] <<= 1; 
    snstring[9] &= 0x07; 
    pwd = atoi32(snstring); 
    return (pwd); 
} 

난 다음, 내가 시도 C# 코드로이 변환해야합니다

private uint ComputeKey(uint snumber) 
     { 
      char[] snstring = new char[11]; 
      UInt32 pwd; 
      int i = 0; 
      snstring = snumber.ToString().ToCharArray(); 

      do 
      { 
       snstring[i + 1] = Convert.ToChar(snstring[i + 1] - '0'); 
       snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1])); 
       snstring[i] &= Convert.ToChar(Convert.ToInt32(0x07)); 
       i++; 
      } while (i < 9); 
      snstring[9] <<= 1; 
      snstring[9] &= Convert.ToChar(0x07); 
      pwd = Convert.ToUInt32(snstring); 
      return (pwd); 
     } 

프로그램 snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1]));이 라인에서 예외가 발생합니다.

또 다른 눈에 띄는 행동, 예를 들어 내가 snstring[i+1]이 라인 snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1])); 값에,

다음 151,972,634

로 입력을해야한다는 것입니다 것은 '\u0005' 이며 OverflowException이 처리되지 않은이었다가 발생합니다.

내가 무엇을해야하는지 잘 모르겠다. 어떤 도움을 주시면 감사하겠습니다.

+0

결과 (snstring [I + 1])'은 범위 밖에 숯불로 변환 될 수 없다. 받아 들여. –

+0

'int'와'char' 사이를 앞뒤로 변환하는 것을 멈 춥니 다. 일단'int'로 변환하고, 모든 비트 twiddling을 적용한 다음 다시 변환하십시오. – Phylogenesis

+0

좋은 이전 workign c 함수를 사용하지 않는 이유는 무엇입니까? 참조 : http://stackoverflow.com/a/11593657/3989673 – bigahega

답변

1

나는 비슷한 작업을 수행했습니다. 즉, 숫자를 입력으로 사용하고 코드가 C#에서 수행하는 작업을 정확하게 수행했습니다. 나는 문자열을 입력으로 받고 문자열을 반환하고있다. 아래 코드이다 : '~ Convert.ToInt32의

private string ComputeKey(string serialnumber) 
     { 
      if (string.IsNullOrEmpty(serialnumber)) 
      { 
       throw new Exception("Cannot generate a key from a null or empty string"); 
      } 

      serialnumber += '\0'; 
      var length = serialnumber.Length; 
      byte[] snbytes = Encoding.UTF8.GetBytes(serialnumber); 
      for (int i = 0; i < length - 1; i++) 
      { 
       snbytes[i + 1] -= 0x30; 
       snbytes[i] = (byte)~snbytes[i + 1]; 
       snbytes[i] &= 0x07; 
      } 
      snbytes[length - 1] <<= 1; 
      snbytes[length - 1] &= 0x07; 

      var sb = new StringBuilder(); 
      for (int j = 0; j < length - 1; j++) 
      { 
       sb.Append(snbytes[j].ToString()); 
      } 

      return sb.ToString(); 
     } 
1

char을 나타내는 32 비트 int 비트를 플립하면 (항상 C에서 1 바이트) 0xFF으로 설정된 상위 3 바이트가됩니다. 그러나 C는 char에 할당시 상위 바이트를 행복하게 잘라내는 반면 C#의 변환기는 예외를 throw합니다.

당신은 C가 무엇에 맞게 변환 대신에 캐스트를 사용하여이 문제를 해결할 수 있습니다

snstring[i+1] -= '0'; 
snstring[i] = (char)(~snstring[i+1] & 0x07); 

본질적으로, 캐스팅 C가 기본적으로 수행하는 것과 같은 일을 명시 적으로 C 번호를 알려줍니다.

+1

정수 승격으로 인해 C에서 0xFF로 설정된 상위 바이트로 끝납니다. 그러나 C는 느슨하고 할당을 통해 진단을 생성하지 않고 암시 적 변환을 lvalue 유형으로 곧바로 수행 할 수 있습니다. 간단히 말해서, 튼튼한 C 코드는'~'바로 뒤에 의도 된 타입으로 암시 적으로 캐스트를해야합니다. 예를 들어'(unsigned char) ~ snstring [i + 1]'. (C 언어에서는 signedness가 잘못 정의되어 있기 때문에'char'를 사용하고 싶지 않습니다.) – Lundin

+0

고쳐 주셔서 감사합니다! – dasblinkenlight