-3

What is the difference between these two declarations?

    long int n=12;
    long int n=12l;
    int n=12l;

and
How does an unsigned variable store signed values?

    unsigned int number=-13;
Kitswas
  • 1,134
  • 1
  • 13
  • 30
  • 12 is an int constant, 12l is a long int constant. The conversion from the right-hand value to the left-hand type is specified by the standard. – stark Jun 26 '21 at 14:43
  • 1
    Does this answer your question? [what is the reason for explicitly declaring L or UL for long values](https://stackoverflow.com/questions/13134956/what-is-the-reason-for-explicitly-declaring-l-or-ul-for-long-values) – vandench Jun 27 '21 at 16:24

2 Answers2

1

What is the difference between these declarations?

long int n=12;

An int value 12 is assigned to the long variable n.

long int n=12l;

A long value 12l is assigned to the long variable n.

int n=12l;

A long value 12l is assigned to the int variable n.

How can an unsigned variable allow signed values?

unsigned int number=-13;

Why do you think so? This question is a duplicate.

Kitswas
  • 1,134
  • 1
  • 13
  • 30
1

Why do we use suffix in c variables?

These suffixes are not in the variables. They are in constants. We use suffixes, sometimes, to control the types of the constants.

long int n = 12;

In this, 12 is a constant of type int. Small decimal numerals with no suffix are int by default. A numeral for an integer too big to represent in int will be long int or long long int, or possibly a compiler-specific wider type.

Since n is declared to be long int, the int 12 will be converted to a long int for the initialization. This conversion will not change the value.

long int n = 12l;

Here, 12l is a constant of type long int. Since it is used to initialize a long int, no conversion is necessary.

int n = 12l;

Again, 12l is a long int. However, since it is used to initialize an int, it will be converted to int. Since int can represent the value 12, this conversion will not change the value. If the constant were too large to represent in an int, then the conversion would change the value, in some implementation-defined way.

As to why we use suffixes sometimes, consider 1 << 31. The 1 is an int, and we shift it left 31 bits. In C implementations common today, an int has 32 bits, and it can represent numbers from −231 to +231−1. However, 1 << 31 would produce 231, which overflows this int range. The C standard does not define the behavior when that overflow occurs.

To avoid this, we might write 1u << 31. Then 1u is an unsigned int, which can represent numbers from 0 to +232−1. Then 231 fits in this, and there is no overflow. Alternately, if we know long int is 64 bits in the C implementation we are using, we might use 1l << 31, depending on our needs. 1 << 31 would overflow, but 1l << 31 would not.

The u suffix makes a decimal constant unsigned int, unsigned long int, or unsigned long long int, as necessary to holds its value (or possibly a wider type supported by the compiler).

The l suffix makes a decimal constant at least long int (skipping int), but the constant will still be long long int if its value is too large for long int.

If an integer constant is written using octal (starts with 0) or hexadecimal (starts with 0x), then it both signed and unsigned types are considered until one is found that can represent its value: int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, and then compiler-specific types.

unsigned int number = -13;

Here 13 is an int constant, and the - is the negation operator, so the result is an int with value −13. (Note there are no negative integer constants in C; you make a negative integer by negating an integer constant.)

Since it is used to initialize an unsigned int, it is converted to unsigned int. When C converts an integer to an unsigned integer type of width M (meaning the type uses M bits to represent values), it is “wrapped” modulo 2M. This means 2M is added to or subtracted from the value until the result is representable in the destination type. For −13 and a 32-bit unsigned int, wrapping −13 modulo 232 produces −13 + 4,294,967,296 = 4,294,967,283.

Wrapping modulo 2M produces the same result as if you wrote the starting number in binary (using two’s complement with more than M bits, if the number is negative) and removed all but the last M bits. For example, −13 in 64-bit two’s complement is 11111111111111111111111111111111111111111111111111111111111100112 = FFFFFFFFFFFFFFF316. The last 32 bits are 111111111111111111111111111100112 = FFFFFFF316. In plain binary (not two’s complement), that is 4,294,967,283.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312