Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-9'223'372'036'854'775'808LL is unsigned

Since C++20 two's complement representation is the only representation allowed by the standard, with the guaranteed range from -2N-1 to +2N-1-1. So for a 64-bit signed integer type the range goes from -9'223'372'036'854'775'808 to 9'223'372'036'854'775'807. However, this code does not compile on Visual Studio (and neither on gcc)

int main()
{
    long long x{-9'223'372'036'854'775'808LL};
    // error C4146: unary minus operator applied to unsigned type, result still unsigned
    // error C2397: conversion from 'unsigned __int64' to '__int64' requires a narrowing conversion
}

Yet, if I replace the code with long long x{-9'223'372'036'854'775'807LL - 1} compiles just fine and x holds the correct value. What am I not getting here?

like image 683
user7769147 Avatar asked Apr 18 '20 13:04

user7769147


People also ask

What is the difference between signed and unsigned in C?

In C and C++. unsigned = unsigned int (Integer type) signed = signed int (Integer type) An unsigned integer containing n bits can have a value between 0 and (2^n-1) , which is 2^n different values. An unsigned integer is either positive or zero.

What does unsigned int mean?

So "unsigned" is a shorthand for "unsigned int". This has been considered bad practice for a long time, but there is still a fair amount of code out there that uses it. Show activity on this post. in C, unsigned is a shortcut for unsigned int. And it is also possible to declare a unsigned long (it will be a unsigned long int ).

What is a signed and unsigned binary?

A signed binary is a specific data type of a signed variable. 1. Unsigned Numbers: Unsigned numbers don’t have any sign, these can contain only magnitude of the number. So, representation of unsigned binary numbers are all positive numbers only.

What is an unsigned data type in C?

Syntax In C programming language, unsigned data type is one of the type modifiers which are used for altering the data storage of a data type. In C, usually, we have integer (int) data type by default are signed where it can store values both negative and positive values. Let us see how to declare it in the C programs.


2 Answers

Without the LL suffix the type is taken as the first type in the list in the standard that fits. If you use the LL suffix then the value will specifically have type long long. However either way 9'223'372'036'854'775'808 is too large to fit in a long long (which is the largest signed type) so some compilers allow it as an extension to become unsigned long long, hence the warning. GCC and Clang do actually warn in that case. Contrary to many people's belief, there's no negative integer literal in C or C++. -9'223'372'036'854'775'808 is a unary minus applying to the integer 9'223'372'036'854'775'808

The type of the literal

The type of the integer literal is the first type in which the value can fit, from the list of types which depends on which numeric base and which integer-suffix was used.

  • no suffix
  • decimal bases:
    • int
    • long int
    • long long int (since C++11)
  • binary, octal, or hexadecimal bases:
    • int
    • unsigned int
    • long int
    • unsigned long int
    • long long int (since C++11)
    • unsigned long long int (since C++11)
  • ...
  • suffix: ll or LL
  • decimal bases:
    • long long int (since C++11)
  • binary, octal, or hexadecimal bases
    • long long int
    • unsigned long long int (since C++11)
  • ...

If the value of the integer literal is too big to fit in any of the types allowed by suffix/base combination and the compiler supports extended integer types (such as __int128) the literal may be given the extended integer type -- otherwise the program is ill-formed.

In fact there are a lot of similar issues in the past where -2147483648 is also unsigned because at that time long long wasn't in the C and C++ standards and the largest type is unsigned long:

  • Why do we define INT_MIN as -INT_MAX - 1?
  • (-2147483648> 0) returns true in C++?
  • Why does the smallest int, −2147483648, have type 'long'?
  • Why is 0 < -0x80000000?
  • Why does MSVC pick a long long as the type for -2147483648?
  • C: Casting minimum 32-bit integer (-2147483648) to float gives positive number (2147483648.0)
like image 193
phuclv Avatar answered Nov 06 '22 03:11

phuclv


This post answers it. In short, unary - operator is not part of integer literal.

With -9'223'372'036'854'775'807LL - 1 you start off landing within the confines of long long, set it to negative, then subtract 1. The other immediatelly starts outside of bounds.

like image 39
buer Avatar answered Nov 06 '22 02:11

buer