Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 22, 2014 Question about iteger literals | ||||
---|---|---|---|---|
| ||||
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? |
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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: http://forum.dlang.org/thread/lnrc8l$1254$1@digitalmars.com 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 |
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > 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?
|
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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) |
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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
|
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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 your thinking.
Bye,
bearophile
|
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > 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 your thinking.
Ok. Thank you! I never thought about it that way
|
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to 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? |
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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
|
June 22, 2014 Re: Question about iteger literals | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | 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.
|
Copyright © 1999-2021 by the D Language Foundation