서명되지 않은 부호로 변환에서는 C-그것은 항상 안전합니까?

StackOverflow https://stackoverflow.com/questions/50605

  •  09-06-2019
  •  | 
  •  

문제

가정하자 나는 다음과 같은 C 코드입니다.

unsigned int u = 1234;
int i = -5678;

unsigned int result = u + i;

무엇을 암시적 변환을에 여기에,그리고 이 코드에 대한 안전의 모든 값 ui?(안전하다는 의미에서도 불구 결과 이 예시에서 오버플로우하는 몇몇 거대한 양수,나는 그것을 다시 int 와 실제 결과입니다.)

도움이 되었습니까?

해결책

짧은 대답

귀하의 i 될 것입 변환 을 부호 없는 정수에 의해 추가 UINT_MAX + 1, 다음을 추가로 수행됩 서명되지 않은 값의 결과로,큰 result (값에 따라 ui).

긴 답변

에 따라 C99 표준:

6.3.1.8 일반적인 산술 전환

  1. 는 경우에는 모두 피연산자가 동일한 유형이 더 이상의 전환이 필요합니다.
  2. 그렇지 않은 경우,피연산자가 모두 서명한 정수 형식 또는 모두가 서명되지 않는 정수형,피연산자의 형식과 더 적은 정수로 변환 순위로 변환하여 피연산자의 유형으로 더 큰 순위입니다.
  3. 그렇지 않은 경우,피연산자가 서명되지 않는 정수형 순위가 크거나 같음의 계급의 유형이 다른 연산자,그 다음 연산자로 서명된 정수형 변환기 유형 피연산자의 부호 없는 정수형입니다.
  4. 그렇지 않은 경우,형식 피연산자의 서명된 정수 입력할 수 있습을 나타내의 모든 값의 형식 피연산자의 서명이 없는 정수형,다음 연산자와 부호 없는 정수형 변환기 유형 피연산자의 서명된 정수 입력.
  5. 그렇지 않으면 모두 피연산자로 변환된 부호 없는 정수형 해당하는 유형 피연산자의 서명된 정수 입력.

귀하의 경우에,우리는 하나 unsigned int(u 고)signed int(i).참조(3)위에,이후 피연산자를 모두 동일한 순위를 가지고,당신 i 야 합니다 변환 을 부호 없는 정수입니다.

6.3.1.3 서명 및 부호 없는 정수

  1. 할 때 가치와 정수형 변환기 또는 정수형 이외의 다른 _Bool 는 경우,이 값을 표현할 수 있는 새로운 유형,그것은 변경되지 않습니다.
  2. 그렇지 않은 경우,새로운 유형이 서명되지 않은 값이 변환되는 반복적으로 추가하거나 빼는 하나 이상의 최대값을 표현할 수 있는 새로운 유형 될 때까지 가치의 범위에 새로운 유형입니다.
  3. 그렇지 않으면,새로운 유형이 서명되고 가치로 표현할 수 없다;거나 결과는 구현 시 정의는 구현된 신호가 발생합니다.

지금 우리에게 필요한 참조(2)above.귀하의 i 로 변환되는 값을 추가하여 UINT_MAX + 1.그래서 결과 방법에 따라 달라집니다 UINT_MAX 에 정의의 구현합니다.그것은 큰 것입니다,그러나지 않기 때문:

6.2.5 (9)

계산 관련 부호 없는 피연산자 수 없기 때문 결과로 표현할 수 없는 의 결과 unsigned integer 유형 감소한 모듈로는 숫자보다 가장 큰 가치로 표현할 수 있는 결과 유형입니다.

보너스:산술 변환 Semi-WTF

#include <stdio.h>

int main(void)
{
  unsigned int plus_one = 1;
  int minus_one = -1;

  if(plus_one < minus_one)
    printf("1 < -1");
  else
    printf("boring");

  return 0;
}

당신이 링크를 사용할 수 있습니다 이것을 시도해 온라인: https://repl.it/repls/QuickWhimsicalBytes

보너스:산술 변환 Side Effect

산술 변환 규칙을 사용할 수 있는 값의 UINT_MAX 를 초기화하여 서명되지 않은 가치를 -1, ie:

unsigned int umax = -1; // umax set to UINT_MAX

이식할 수에 관계없이 서명한 번호의 표현 시스템이기 때문에 변환의 규칙을 설명한다.이렇게 질문에 대한 더 많은 정보: 그것은 사용하기에 안전 -1 을 설정하는 모든 비트를 사실인가요?

다른 팁

변환에서 서명 서명되지 않는 은 반드시 복사본이나 해석해 표현의 서명된 값입니다.을 인용하는 C 표준(C99 6.3.1.3):

할 때 가치와 정수형 변환기 또는 정수형 이외의 다른 _Bool 는 경우 값을 표현할 수 있는 새로운 유형,그것은 변경되지 않습니다.

그렇지 않은 경우,새로운 유형이 서명되지 않은 값이 변환되는 반복적으로 추가하거나 을 빼서 하나 이상의 최대값을 표현할 수 있는 새로운 유형 까지는 값의 범위에서는 새로운 유형입니다.

그렇지 않으면,새로운 유형이 서명되고 가치로 표현할 수 없다;나 그 결과 구현 시 정의는 구현된 신호가 발생합니다.

에 대한 두 개의 보충 표현하는 거의 보편적인 요즘은 규칙에 해당한 재해석하는 비트입니다.하지만 다른 표현(호 및 크기 또는'보수),C 구현해야합니다 여전히 준비를 위해 동일한 결과,즉 변환할 수 있는지만 복사합니다.예를 들어,(unsigned)-1==uint_max 로 씁에 관계없이의 표현입니다.

일반적으로,변환 C 에서 정의된 작동 값에,지에 표현입니다.

대답을 원래의 질문:

unsigned int u = 1234;
int i = -5678;

unsigned int result = u + i;

I 의 값으로 변환하 unsigned int,항복 UINT_MAX + 1 - 5678.이 값은 다음에 추가 서명되지 않은 가치 1234,항복 UINT_MAX + 1 - 4444.

(와 달리 부호 없는 오버플로,서명 오버플로를 호출합 정의되지 않은 행동이다.랩어라운드는 일반적이지만,에 의해 보장되지 않으 C 표준--와 컴파일러 최적화할 수 있는 위력을 과시 코드에서는 부당한 모델 예측제어 등을 다룬다.)

성경:

  • 또한 작업으로 인 int 로 변환할 unsigned int.
  • 고 가정하고 두 개의 보충 표현하고 균일한 크기의 종류,비트 패턴을 변경하지 않습니다.
  • 변환 unsigned int 을 서명 int 구현 방식에 따라 다릅니다.(그러나 그것은 아마이 작동 방법은 당신이 기대하는 대부분의 플랫폼에서 이러한 일입니다.)
  • 이 규칙은 조금 더 복잡한 경우에 결합의 서명 및 서명 서로 다른 크기입니다.

한 때 서명이 없으며,하나의 서명된 변수 추가(또는 바이너리 작업)을 두는 암시적으로 변환 부호 없는 것,이 경우 그 결과에 큰 결과입니다.

그래서 그것은에서 안전 감각의 결과될 수 있습 거대한 잘못이지만,그것은 결코 충돌이 발생합니다.

변환할 때에 서명되지 않은 부호가 있는 두 가지 방법이 가능합니다.숫자는 긍정적인 유지(또는 해석 등)동일한 값입니다.는 번호가 원래 부정적인 것입니다 지금 해석할 수 있으로 더 긍정적인 숫자입니다.

으로 이전에 응답할 수 있습 캐스팅 사이 앞뒤로 서명 및 부호 없이 문제입니다.국경 경우 대한 서명된 정수이다 -1(0xFFFFFFFF).도 추가하고 빼는 사실을 발견할 수 있습으로 다시 캐스팅하고 있다.

그러나,당신이 할 것 주조,앞뒤로 나는 강하게 이름을 지정하는 변수는 무엇인 유형은 그들이는,예를 들어:

int iValue, iResult;
unsigned int uValue, uResult;

그것은 너무 쉽게 얻을 산만 더 중요한 문제를 잊어있는 변수가 무엇을 입력하는 경우 그들의 이름은 없습니다.당신이 원하지 않을 캐스팅하는 부호를 사용하여 다음을 배열로 인덱스입니다.

무엇을 암시적 변환을은 여기서,

i will be 변환 부호 없는 정수입니다.

이 코드에 대한 안전의 모든 값 u 나는?

에서 안전 감각의 정의 예(참조하십시오 https://stackoverflow.com/a/50632/5083516 ).

규칙을 작성에는 일반적으로 열심히 읽고 표준-말을하지만 본질적으로 어떤 표현에서 사용되었다수의 부호 없는 정수를 포함한 2 개의 보수 표현의 번호입니다.

또한,빼기와 곱게 올바르게 작동에 이 숫자의 결과로 다른 부호 없는 정수를 포함하는 조로 보완 수를 나타내는"실제 결과".

분단과 캐스팅을 크 unsigned integer 유형이 잘 정의된 결과 하지만 그 결과를 얻을 수 없습 2 보수의 표현이"진짜 결과".

(안전하다는 의미에서도 결과는 이 예에서 오버플로우하는 몇몇 거대한 양수,나는 그것을 다시 int 와 실제 결과입니다.)

는 동안 변환에서 서명 서명되지 않는 정의된 기준에 의해 반전 구현 시 정의를 모두 gcc 및 msvc 정의 변환과 같은 당신을 얻을 것이"진짜 결과는"변환하는 경우 2 의 보수에 저장되는 부호 없는 정수를인 정수입니다.나는 당신을 기대를 만날 수 있는 것은 다른 어떤 행동을 보호 시스템을 사용하지 않는 2 개의 보충에 대한 서명된 정수입니다.

https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation https://msdn.microsoft.com/en-us/library/0eex498h.aspx

끔찍한 답변의 풍부한 맛

Ozgur Ozcitak

을 때 당신이 던지기에서 서명 서명되지 않음 (그리고 반대로)부 의 표현하지 않는 번호 변경합니다.어떤 변화가 어떻게 컴파일러 해석 등 비트입니다.

이는 완전히 잘못된 것입니다.

매트 Fredriksson Sekab

한 때 서명이 없으며,하나의 서명 변수 추가(또는 바이너리 운전)모두는 암시적으로 변환 부호 없는 것에 이 경우 그 결과에 큰 결과입니다.

이것은 잘못된 것입니다.Unsigned 수 있으로 승진 수야 그들이 동일한 정밀도로 인해 패딩의 비트 부호 없는 유형입니다.

다.

또한 작업으로 인 int 로 변환할 unsigned int.

잘못입니다.어쩌면 그것은 어쩌면 그것을 하지 않습니다.

변환 unsigned int 을 서명 int 구현 방식에 따라 다릅니다.(지 그것은 아마이 작동 방법은 당신이 기대하는 대부분의 플랫폼에서 이러한 일입니다.)

잘못입니다.그것은 하나 정의되지 않은 동작을 일으키는 원인이 되면 오버플로나의 값이 유지됩니다.

익명

I 의 값으로 변환됩 unsigned int...

잘못입니다.의 정밀도에 따라 달라 집 int 관 unsigned int.

테일러 가격

으로 이전에 응답할 수 있습 주 앞뒤로 사이에 서명하고 서명없이 문제입니다.

잘못입니다.를 저장하는 값의 범위 밖에 서명된 정수의 결과에서 정의되지 않은 행동이다.

지금 마지막 질문에 대답.

해 정밀도의 int 같 unsigned int,u 로 승격되고 서명된 int 고 당신은 값을 얻을 것이다 -4444 에서 식(u+i).이제,한 u 하고 나는 다른 값을 얻을 수 있습니다 오버플로 정의되지 않은 행동하지만 그 정확한 숫자을 얻을 것이 -4444 [1].이 값이 유형 int.그러나 당신이 시도하고 있는 저장하는 값으로 unsigned int 는 것입니다 그래서 그 다음 주에는 unsigned int 와 가치는 결과가 끝나는 것(uint_max 로 씁+1)-4444.

해야의 정밀도 unsigned int 것보다 큰 int,서명된 int 것으로 승격되 unsigned int 산출 가치(uint_max 로 씁+1)-5678 에 추가될 다른 unsigned int1234.해야 u 하고 나는 다른 값을 표현 범위를 벗어{0..uint_max 로 씁}값(uint_max 로 씁+1)하나 추가하거나 뺄 때까지는 결과가 떨어질 내부 범위{0..uint_max 로 씁)없이 정의되지 않은 문제가 발생합니다.

는 무엇입 정밀?

정수 있 패딩 비트,로그인 비트값 비트입니다.호 정수 없는 등록금 분명합니다.Unsigned char 이 더 보장하지 않는 여백 비트입니다.수은 값의 비트 정수가 얼마나 정밀도니다.

[문제점]

매크로 sizeof 매크로 혼자 사용할 수 없습을 결정하는 정밀의 정수한 경우 패딩 비트가 존재한다.의 크기는 바이트 수 없는 옥텟(eight bits)에 의해 정의된 C99.

[1] 오버플로우가 발생할 수 있습 중 하나에서 두 개의 포인트입니다.하나 추가하기 전에(이용촉진)-이 있는 경우 unsigned int 는 맞게 너무 큰 내부 int.오버플로우가 발생할 수 있습 후한 경우에도 unsigned int 었의 범위 내에서 int,첨가한 후 그 결과는 여전히 오버플로우가 발생합니다.


에 없는 나는 최근 대학원 학생을 찾으려고 일)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top