## digitalmars.D.learn - Question about iteger literals

• Uranuz (34/34) Jun 22 2014 I have the following programme
• bearophile (29/37) Jun 22 2014 Better to use this signature (assuming you want a ushort result,
• Uranuz (4/7) Jun 22 2014 I understand what pure, nothrow and @safe mean there. But what
• Uranuz (8/8) Jun 22 2014 In expression
• bearophile (8/13) Jun 22 2014 In D operations among chars return a int. The same happens in
• Uranuz (1/6) Jun 22 2014 Ok. Thank you! I never thought about it that way
• Uranuz (3/3) Jun 22 2014 Another stupid question. Using this logic substraction for two
• bearophile (9/12) Jun 22 2014 There are no stupid questions, there are only some stupid answers.
• Uranuz (24/27) Jun 22 2014 Now this code
• bearophile (15/17) Jun 22 2014 Despite D being only 14 years old, one of its rules is to
• Uranuz (13/13) Jun 22 2014 If these rules are not so clear and have some exceptions (but I
• Steven Schveighoffer (5/8) Jun 23 2014 See integer promotion rules:
• Uranuz (18/27) Jul 20 2014 I see these rules but when I compile following code and it fails
• Uranuz (2/18) Jul 20 2014 I just should forget about all integer type except *int*, because
• bearophile (6/11) Jul 20 2014 In C/C++/D if you sum a types that are smaller than int, you
• Uranuz (21/26) Jul 20 2014 Is there any reasoning why this should remain unchainged? How
• bearophile (7/8) Jun 22 2014 @nogc will be present in dmd 2.066, it means that the function
"Uranuz" <neuranuz gmail.com> writes:
```I have the following programme

import std.stdio;

bool isDigit(char c) nothrow
{
return c >= '0' && c <= '9';
}

ushort hexValue(char c) nothrow
{
if( isDigit(c) )
return c - '0';
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else
return ushort.max;
}

void main()
{
writeln(hexValue('A'));
}

This example is compiling successfully in DMD 2.064 but in DMD
2.065 a got the following error:

/d544/f547.d(12): Error: cannot implicitly convert expression
(cast(int)c - 48) of type int to ushort
/d544/f547.d(14): Error: cannot implicitly convert expression
(cast(int)c - 97 + 10) of type int to ushort
/d544/f547.d(16): Error: cannot implicitly convert expression
(cast(int)c - 65 + 10) of type int to ushort

So I have a question why these expressions are casted to int? I
was thinking that result should be of char type. And it could be
implicitly converted to ushort (because there is enough place to
store result). Is it a bug in compiler or I should insert
explicit casts?
```
Jun 22 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

bool isDigit(char c) nothrow

This function is already in Phobos, it's std.ascii.isDigit.

ushort hexValue(char c) nothrow

Better to use this signature (assuming you want a ushort result,
despite a ubyte suffices and a uint is faster):

ushort hexValue(in char c) pure nothrow  safe  nogc

else
return ushort.max;

Special error values are not very safe. Consider the usage of a
Nullable!(ubyte, ubyte.max) instead, if you can stand the little
abstraction penalty.

why these expressions are casted to int?

Because in C/C++/D if you perform arithmetic operations among
types shorter than int you produce an int.

I was thinking that result should be of char type.

In general it can't be a char.

And it could be implicitly converted to ushort
(because there is enough place to store result).

The precedent compiler version was wrong, and the bug has being
fixed by the great Kenji.

If you have an expression like:

char - 'a' + 10

It means:

[0, 255] - 87

That is [-87, 168] that can't fit in the [0, 65535] range.

Currently in D the range value analysis works only on the current
expression, so the information from the "if(c >= 'a' && c <=
'f')" condition is ignored here.

There are discussions and even code to fix this:
https://github.com/lionello/dmd/compare/if-else-range
https://github.com/D-Programming-Language/dmd/pull/3679

But both Walter and Andrei have so far ignored this significant D
improvement, so I don't know if and when it will be added.

Bye,
bearophile
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
``` ushort hexValue(in char c) pure nothrow  safe  nogc

else
return ushort.max;

I understand what pure, nothrow and  safe mean there. But what
nogc changes in there so I should use this modifier? Is it
logical specifier that this function can be used without garbage
collector or what?
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
```In expression
return c - 'a' + 10;
I could think that 10 has type int and resulting value promoted
to the largest type. But I don't understand why in expression
where both of arguments have type char:
return c - '0';
I have resulting type int. It's very strange for me and looks
very buggy)
```
Jun 22 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

But I don't understand why in expression where both of
arguments have type char:
return c - '0';
I have resulting type int. It's very strange for me and looks
very buggy)

In D operations among chars return a int. The same happens in
C/C++.

If you subtract a char from a char in general you can have a
negative result, that can't fit in a char. So what's buggy is

Bye,
bearophile
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
``` In D operations among chars return a int. The same happens in
C/C++.

If you subtract a char from a char in general you can have a
negative result, that can't fit in a char. So what's buggy is

Ok. Thank you! I never thought about it that way
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
```Another stupid question. Using this logic substraction for two
uint values should return int too, because it can produce
negative result. Am I right or not?
```
Jun 22 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

Another stupid question. Using this logic substraction for two
uint values should return int too, because it can produce
negative result. Am I right or not?

There are no stupid questions, there are only some stupid answers.

Generally uint - uint generates a result with a [-4_294_967_295,
4__294_967_295] range, that can't fit in an integer.

I think D here makes an exception to its rule, to avoid too many
casts. Because too many casts make the code even less safe than
breaking the range assignments rules.

Bye,
bearophile
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
```On Sunday, 22 June 2014 at 11:57:48 UTC, Uranuz wrote:
Another stupid question. Using this logic substraction for two
uint values should return int too, because it can produce
negative result. Am I right or not?

Now this code

import std.stdio;

void main()
{
uint a = 50;
uint b = 60;
auto c = a - b;

writeln(typeid(c));
}
produce output "uint". It's some breakage in my logic. I am
thinking that all integer-like types should behave similar way. I
perceive char type as ubyte, that should be printed as symbol
when using functions like writeln(). But the folowing example

import std.stdio;

void main()
{
ubyte a = 50;
ubyte b = 60;
auto c = a - b;

writeln(typeid(c));
}

produces output "int" like you said. Why there are so complicated
rules in the *new* language. It's hard to understand the logic.
```
Jun 22 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

Why there are so complicated rules in the *new* language.
It's hard to understand the logic.

Despite D being only 14 years old, one of its rules is to
(usually) give the same results if you write code that is valid
in C. This means it has to follow many rules of C language. If
you try your code in C you will see some similar results. This
rule of D is quite handy.

Other reasons for the current design of D is that sometimes
practicality beats design purity, because D is an engineering
product.

And I guess another reason is that Walter is not a mathematician
nor a computer science theorist, so he has not seen some more
principled designs, or he has not appreciated them because of
their more formal nature.

Bye,
bearophile
```
Jun 22 2014
"Uranuz" <neuranuz gmail.com> writes:
```If these rules are not so clear and have some exceptions (but I
don't understand why they are needed) then some documentation
substraction like uint, and char substraction like char. If we
will changing all the types it will be kind of mess. Using this
logic we should have some bigger type for int multiplication
operator to fit in result of multiplication of int.max*int.max. I
know that some assembler operations do this and multiplication of
two registers with byte size results in placing product into two
result register. But in context of higher level programming
language it's better to have better type consistensy. Or we will
nead a bigger type to store product for ulong.max*ulong.max
result. Is it good or not?
```
Jun 22 2014
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```On Sun, 22 Jun 2014 08:23:45 -0400, Uranuz <neuranuz gmail.com> wrote:

If these rules are not so clear and have some exceptions (but I don't
understand why they are needed) then some documentation needed about
this.

See integer promotion rules:

http://dlang.org/type.html#Integer%20Promotions

And the section below it.

-Steve
```
Jun 23 2014
"Uranuz" <neuranuz gmail.com> writes:
```On Monday, 23 June 2014 at 18:32:38 UTC, Steven Schveighoffer
wrote:
On Sun, 22 Jun 2014 08:23:45 -0400, Uranuz <neuranuz gmail.com>
wrote:

If these rules are not so clear and have some exceptions (but
I don't understand why they are needed) then some

See integer promotion rules:

http://dlang.org/type.html#Integer%20Promotions

And the section below it.

-Steve

I see these rules but when I compile following code and it fails
with error it looks VERY stupid.

import std.stdio;

void main()
{
ubyte a = 15;
ubyte b = 10;

ubyte c = a + b; //What is happening there?! AAAAARGH! Are you
joking?!

}

Compilation output:
/d837/f382.d(9): Error: cannot implicitly convert expression
(cast(int)a + cast(int)b) of type int to ubyte

I'm just crazy about it! How could it happen?!
```
Jul 20 2014
"Uranuz" <neuranuz gmail.com> writes:
``` I see these rules but when I compile following code and it
fails with error it looks VERY stupid.

import std.stdio;

void main()
{
ubyte a = 15;
ubyte b = 10;

ubyte c = a + b; //What is happening there?! AAAAARGH! Are you
joking?!

}

Compilation output:
/d837/f382.d(9): Error: cannot implicitly convert expression
(cast(int)a + cast(int)b) of type int to ubyte

I'm just crazy about it! How could it happen?!

I just should forget about all integer type except *int*, because
it make my head just explode!!!
```
Jul 20 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

ubyte a = 15;
ubyte b = 10;

ubyte c = a + b; //What is happening there?! AAAAARGH! Are you
joking?!

In C/C++/D if you sum a types that are smaller than int, you
obtain an int. D has copied C for backwards compatibility with C
code.

Bye,
bearophile
```
Jul 20 2014
"Uranuz" <neuranuz gmail.com> writes:
``` In C/C++/D if you sum a types that are smaller than int, you
obtain an int. D has copied C for backwards compatibility with
C code.

Bye,
bearophile

Is there any reasoning why this should remain unchainged? How
could it break interface between languages? And also this code
succesfully compiles and runs in C++.

#include <iostream>

using namespace std;

int main()
{
unsigned short a = 15;
unsigned short b = 10;

unsigned short c = a + b;  //There is no problem

cout << c << endl;

return 0;
}

As D compiler doesn't need to compile C programme and have
compatible operations with types. Why we still should keep this
garbage?!

I don't know the right solution but I believe that previous
example illustrates some contradiction in integer types system
design or implementation.

Why we dont promote *ulong* and *long* to int? Let's also promote
string into array of ints?! Can't believe it!
```
Jul 20 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Uranuz:

But what  nogc changes in there so I should use this modifier?

nogc will be present in dmd 2.066, it means that the function
(and all the functions it calls) can't perform operations that
cause a call to GC functions.

Sometimes GC operations are a source of performance loss.

Bye,
bearophile
```
Jun 22 2014