2011-01-02 5 views
4

이것은 정말 이상합니다. 아무도 이것을 설명 할 수 있습니까?C에서 한 줄에 바이트를 빼는 방법 #

이 코드는 작동하지 않습니다

const byte ASC_OFFSET = 96; 
string Upright = "firefly"; 
byte c7 = (byte)Upright[6] - ASC_OFFSET; 
//Cannot implicitly convert type 'int' to 'byte'. 

이 코드는 작동하지 않습니다

const byte ASC_OFFSET = 96; 
string Upright = "firefly"; 
byte c7 = (byte)Upright[6] - (byte)ASC_OFFSET; 
//Cannot implicitly convert type 'int' to 'byte'. 

을하지만, 별도의 줄에 빼기를 넣어 잘 작동합니다 :

const byte ASC_OFFSET = 96; 
string Upright = "firefly"; 
byte c7 = (byte)Upright[6]; 
c7 -= ASC_OFFSET; 

나는 문장을 별도의 줄에 두는 것을 꺼려한다. 그렇지만 나는 궁금해해야한다. ...

왜?

답변

3

나는 이것도 전에 주목했습니다. 제 생각에는 -= 연산자가 바이트 유형에 대해 미리 정의 되었기 때문입니다. 반면에 전자의 경우에는 int을 실제로는 byte 안에 넣는 것이 허용되지 않습니다. 이 작업을 수행 한 이유는 반드시 의미가있는 것은 아니지만 규칙과 일치합니다. 이전 사례에서는 컴파일러가 할당을 수행 할 때 - 연산자에서 "엿보기"할 수 없기 때문입니다.

당신이 정말로 말하는 대신에, 한 줄에 빼기해야하는 경우 :

byte c7 = (byte)Upright[6] - ASC_OFFSET; 

말 :

byte c7 = (byte)(Upright[6] - ASC_OFFSET); 
+0

안녕하세요 램버트 - 오늘 밤에 롤에 올거야! 나는 int와 back에 대한 round-trip을 받아들이는 것보다 약간의 unpretty 코드를 가지고 있기 때문에 여러 줄에 코드를 보관할 예정 임에도 불구하고 이것을 받아들입니다. – Flipster

+0

하하 감사합니다! :) AFAIK, 코드에서 보든 상관없이 모든 * 산술 연산에 왕복 *이 발생합니다. 내가 올바르게 기억한다면, 모든 연산은 데이터 타입이 무엇이든 관계없이 CPU의 고유 한 크기로 발생합니다. 둘 중 하나를 사용하여 실제로 아무 것도 저장하지 않습니다. (나는 이것을 재확인 할 것이고, 내가 틀렸다면 나는 여기에 게시 할 것이다.) – Mehrdad

+0

우. 흥미 롭 군. 몇 초 동안 수천 번 호출되는 비트/바이트 수준의 작업을 수행하고 있으며 모든 것을 바이트로 유지하는 것이 int로 작업하는 것보다 빠르다는 것을 알았습니다. 나는 그것이 사실이 아닌지 알고 싶어 할 것입니다. 감사! – Flipster

7

byte 작업 (int 결과 왜 여기 참조) 1 때문입니다 : http://blogs.msdn.com/b/oldnewthing/archive/2004/03/10/87247.aspx를) 및 2) 다음 C# 코드

c7 -= ASC_OFFSET; 

14.14.2 복합 할당 : "마술"

c7 = (byte)(c7 - ASC_OFFSET); 

에 장면 뒤에 컴파일이됩니다 이것은 명시 적으로 여기에 C#을 사양에 설명되어 있습니다

형태의 X의 동작 op = y는 이원 연산자 과부하 해결 (§14.2.4)을 적용하여 처리 된 이고 과 같이 작업이 작성되었습니다. 이어서 ,

하기 • 선택된 오퍼레이터의 리턴 타입 X의 종류에 내재적 전환 인 경우는 상기 동작의 x 제외한 X = X 연산 Y, 으로 평가 한 번만 계산된다.

그렇지 않으면 선택된 연산자가 미리 정의 된 연산자 인 경우 선택한 연산자의 반환 형식이 명시 적으로 x 유형으로 변환 될 수 있고 y가 암시 적으로 x 유형으로 변환 될 수 있거나 연산자가 a이면 시프트 연산자 인 경우 연산은 x = (T) (x op y)로 평가됩니다. 여기서 T는 x의 유형입니다. 단, x는 한 번만 계산됩니다. •

은 그렇지 않으면, 복합 대입은 무효이며, 컴파일 타임 오류 는

+0

환상적인 사이먼! 거기에 훌륭한 정보가 있습니다. 대답을 아직 선택하지 않았다면 ... – Flipster

+0

@FlipScript - 내 행운의 날이 아닙니다 :-) –

+0

당신은 정말 그 대답을받을 자격이 있습니다. :) – Mehrdad

4

컴파일하지 않는 첫 번째 두 샘플은 이유를 때문에 발생합니다 :

  • 캐스트는 빼기보다 "더 단단합니다". 즉 '(C) d-e'는 '(C) (d-e)'가 아니라 '((C) d) -e'를 의미한다. 형 변환 연산자가 우선 순위가 높습니다.
  • 따라서 빼기에 대한 피연산자의 유형은 형변환에 관계없이 byte입니다.
  • 바이트에 대해 정의 된 빼기 연산자가 없기 때문에 뺄셈 유형은 int입니다.
  • 따라서 캐스팅이없는 바이트에 int를 할당하는 것은 불법입니다.

바이트에 빼기 연산자가 없기 때문에 7 바이트를 포함하고 8 바이트가 포함 된 바이트를 뺀 것으로 가정하면 255 바이트가됩니까? 나는 대부분의 사람들이 그것이 int -1이되기를 원할 것이라고 생각한다.

마지막으로 왜이 부분에서 바이트 단위로이 작업을 수행하고 있습니까? 이것은 의미가 없습니다. Chars는 C#에서는 바이트가 아닙니다. 문자에 대한 산술 연산을 수행하려면 왜 바이트로 손실되고 위험한 변환을 수행하는 대신 문자 96을 숯 'y'에서 뺄까요?

+0

안녕하세요 Eric. 사실, 바이트에 대한 뺄셈 연산자는 완벽하다고 생각합니다. 8을 포함하는 바이트에서 7을 포함하는 바이트를 빼면 1을 포함하는 바이트가 남습니다.7에서 8을 뺀 것은 uint16 또는 uint32 ("uint8"대신)에서 동일하게 수행하는 것과 마찬가지로 오버플로가 발생합니다. 바이트를 뺄 수 있습니다. 컴파일러는 동일한 작업을 수행 할 수 있어야합니다. – Flipster

+0

바이트 산술은 14 문자 문자열에 대한 해시 코드를 충돌이없는 32 비트 정수로 빠르게 계산하기위한 것입니다. 믿거 나 말거나, 가능합니다 (우리의 데이터 세트로, 어쨌든). 그런데 왜 char에서 byte 로의 변환이 "손실되고 위험한"것이라고 말합니까? 나는 그것이 무손실이면서 안전하다는 것을 상상할 수 없다. – Flipster

+0

@FlipScript - 'Â'을 바이트로 변환하는 무손실 방법은 무엇입니까? – kvb

관련 문제