Jump to page: 1 2
Thread overview
Question about iteger literals
Jun 22, 2014
Uranuz
Jun 22, 2014
bearophile
Jun 22, 2014
Uranuz
Jun 22, 2014
Uranuz
Jun 22, 2014
bearophile
Jun 22, 2014
Uranuz
Jun 22, 2014
Uranuz
Jun 22, 2014
bearophile
Jun 22, 2014
Uranuz
Jun 22, 2014
bearophile
Jun 22, 2014
Uranuz
Jul 20, 2014
Uranuz
Jul 20, 2014
Uranuz
Jul 20, 2014
bearophile
Jul 20, 2014
Uranuz
Jun 22, 2014
bearophile
June 22, 2014
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
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
> 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
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
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
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
> 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
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
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
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.
« First   ‹ Prev
1 2