programing tip

경고-부호있는 정수 식과 부호없는 정수 식 비교

itbloger 2020. 11. 28. 08:49
반응형

경고-부호있는 정수 식과 부호없는 정수 식 비교


저는 현재 Accelerated C ++를 통해 작업 하고 있으며 연습 2-3에서 문제를 발견했습니다.

프로그램에 대한 간략한 개요 -프로그램은 기본적으로 이름을 취한 다음 별표 프레임 안에 인사말을 표시합니다. 즉, Hello! *로 둘러싸여 있습니다.

연습 -예제 프로그램에서 저자 const int는 인사말과 별표 사이의 여백 (빈 공간)을 결정하는 데 사용 합니다. 그런 다음 독자에게 연습의 일부로 사용자에게 원하는 패딩 크기에 대한 입력을 요청합니다.

이 모든 것이 충분히 쉬운 것 같습니다. 사용자에게 두 개의 정수 ( int)를 요청하고 저장하고 프로그램을 변경 하여이 정수 를 사용하도록 변경하고 컴파일 할 때 다음 경고가 표시되지만 작성자가 사용한 정수를 제거합니다.

Exercise2-3.cpp : 46 : 경고 : 부호있는 정수 식과 부호없는 정수 식 비교

몇 가지 조사 결과 코드가 위의 정수 ( int) 중 하나 를 a string::size_type비교하려고 시도하기 때문인 것으로 보입니다 . 하지만 궁금합니다. 이것은 정수 중 하나를 변경해야 함을 의미 unsigned int합니까? 내 정수가 부호가 있는지 여부를 명시 적으로 나타내는 것이 중요합니까?

 cout << "Please enter the size of the frame between top and bottom you would like ";
 int padtopbottom;
 cin >> padtopbottom;

 cout << "Please enter size of the frame from each side you would like: ";
 unsigned int padsides; 
 cin >> padsides;

 string::size_type c = 0; // definition of c in the program
 if (r == padtopbottom + 1 && c == padsides + 1) { // where the error occurs

위의 코드는 관련 코드 입니다. 인사말이 얼마나 오래 걸릴지 모르기 때문에 c유형입니다. string::size_type하지만 작성자의 코드가 사용할 때 문제가 발생하지 않았는데 왜 지금이 문제가 발생 const int합니까? 또한 Accelerated C ++를 완료 한 사람이라면 이 책의 뒷부분에서 설명 할 것입니까?

나는 Geany를 통해 g ++를 사용하여 Linux Mint를 사용하고 있습니다. 그게 도움이되거나 차이가 나는 경우 (무엇인지 결정할 때 할 수 있다고 읽었습니다 string::size_type).


일반적으로 변수를 선언하는 것이 좋습니다 unsigned또는 size_t그들이 크기에 비해 될 경우,이 문제를 방지 할 수 있습니다. 가능하면 비교할 정확한 유형을 사용하십시오 (예 : 의 길이 std::string::size_type와 비교할 때 사용 std::string).

부호있는 정수와 부호없는 정수의 범위가 다르고 서로 비교할 때 결과가 놀라 울 수 있기 때문에 컴파일러는 부호있는 형식과 부호없는 형식을 비교할 때 경고를 표시합니다. 이러한 비교를 수행해야하는 경우 변환이 유효한지 확인한 후 값 중 하나를 다른 값과 호환되는 유형으로 명시 적으로 변환해야합니다. 예를 들면 :

unsigned u = GetSomeUnsignedValue();
int i = GetSomeSignedValue();

if (i >= 0)
{
    // i is nonnegative, so it is safe to cast to unsigned value
    if ((unsigned)i >= u)
        iIsGreaterThanOrEqualToU();
    else
        iIsLessThanU();
}
else
{
    iIsNegative();
}

어제 Accelerated C ++에서 2-3 번 문제를 해결하면서 똑같은 문제가 발생했습니다. 핵심은 비교할 모든 변수 (부울 연산자 사용)를 호환 가능한 유형으로 변경하는 것입니다. 이 경우 string::size_type(또는 을 의미 unsigned int하지만이 예제에서는 전자를 사용하므로 둘이 기술적으로 호환 가능하더라도 그대로 유지하겠습니다).

원래 코드에서 정확히 지적했듯이 c 카운터 (책의 섹션 2.5의 30 페이지)에 대해 정확히이 작업을 수행했습니다.

무엇보다 복잡한 예제를 만드는 것은 다른 패딩 변수 (padsides 및 padtopbottom)뿐만 아니라 모든 카운터가해야한다는 것입니다 또한 으로 변경 string::size_type.

예를 들어 게시 한 코드는 다음과 같이 표시됩니다.

cout << "Please enter the size of the frame between top and bottom";
string::size_type padtopbottom;
cin >> padtopbottom;

cout << "Please enter size of the frame from each side you would like: ";
string::size_type padsides; 
cin >> padsides;

string::size_type c = 0; // definition of c in the program

if (r == padtopbottom + 1 && c == padsides + 1) { // where the error no longer occurs

이전 조건에서 변수 r을 루프 string::size_type에서 a로 초기화하지 않으면 오류가 발생합니다 for. 따라서 다음과 같이 for 루프를 초기화해야합니다.

    for (string::size_type r=0; r!=rows; ++r)   //If r and rows are string::size_type, no error!

So, basically, once you introduce a string::size_type variable into the mix, any time you want to perform a boolean operation on that item, all operands must have a compatible type for it to compile without warnings.


The important difference between signed and unsigned ints is the interpretation of the last bit. The last bit in signed types represent the sign of the number, meaning: e.g:

0001 is 1 signed and unsigned 1001 is -1 signed and 9 unsigned

(I avoided the whole complement issue for clarity of explanation! This is not exactly how ints are represented in memory!)

You can imagine that it makes a difference to know if you compare with -1 or with +9. In many cases, programmers are just too lazy to declare counting ints as unsigned (bloating the for loop head f.i.) It is usually not an issue because with ints you have to count to 2^31 until your sign bit bites you. That's why it is only a warning. Because we are too lazy to write 'unsigned' instead of 'int'.


At the extreme ranges, an unsigned int can become larger than an int.
Therefore, the compiler generates a warning. If you are sure that this is not a problem, feel free to cast the types to the same type so the warning disappears (use C++ cast so that they are easy to spot).

Alternatively, make the variables the same type to stop the compiler from complaining.
I mean, is it possible to have a negative padding? If so then keep it as an int. Otherwise you should probably use unsigned int and let the stream catch the situations where the user types in a negative number.


or use this header library and write:

// |notEqaul|less|lessEqual|greater|greaterEqual
if(sweet::equal(valueA,valueB))

and don't care about signed/unsigned or different sizes


The primary issue is that underlying hardware, the CPU, only has instructions to compare two signed values or compare two unsigned values. If you pass the unsigned comparison instruction a signed, negative value, it will treat it as a large positive number. So, -1, the bit pattern with all bits on (twos complement), becomes the maximum unsigned value for the same number of bits.

8-bits: -1 signed is the same bits as 255 unsigned 16-bits: -1 signed is the same bits as 65535 unsigned etc.

So, if you have the following code:

int fd;
fd = open( .... );

int cnt;
SomeType buf;

cnt = read( fd, &buf, sizeof(buf) );

if( cnt < sizeof(buf) ) {
    perror("read error");
}

you will find that if the read(2) call fails due to the file descriptor becoming invalid (or some other error), that cnt will be set to -1. When comparing to sizeof(buf), an unsigned value, the if() statement will be false because 0xffffffff is not less than sizeof() some (reasonable, not concocted to be max size) data structure.

Thus, you have to write the above if, to remove the signed/unsigned warning as:

if( cnt < 0 || (size_t)cnt < sizeof(buf) ) {
    perror("read error");
}

This just speaks loudly to the problems.

1.  Introduction of size_t and other datatypes was crafted to mostly work, 
    not engineered, with language changes, to be explicitly robust and 
    fool proof.
2.  Overall, C/C++ data types should just be signed, as Java correctly
    implemented.

If you have values so large that you can't find a signed value type that works, you are using too small of a processor or too large of a magnitude of values in your language of choice. If, like with money, every digit counts, there are systems to use in most languages which provide you infinite digits of precision. C/C++ just doesn't do this well, and you have to be very explicit about everything around types as mentioned in many of the other answers here.

참고URL : https://stackoverflow.com/questions/3660901/a-warning-comparison-between-signed-and-unsigned-integer-expressions

반응형