March 20, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | Roberto Mariottini wrote: > "Pavel Minayev" <evilone@omen.ru> ha scritto nel messaggio > news:a79q0b$20bt$1@digitaldaemon.com... > >>"Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message >>news:a79gcd$1rhf$1@digitaldaemon.com... >> >> >>>I'm very disappointed with this. >>>I've programmed C for more than ten years now, and C++ for nearly 10. >>>And I NEVER use unsigneds [snip] I'll guess that you don't right-shift very often. :) > They are used anyway. Every int can be used as unsigned without problems. > In fact they are almost the same type. > > int i = MAX_INT + 13; // you can use the exact literal if you know it This probably issues a warning on some or most compilers. > printf("%u", i); // prints out MAX_INT + 13 This probably issues a warning in GCC, which does printf typechecking. If a warning is not issued, that says more about printf and the varargs mechanism than about unsigned. > Yes, but what's a warning? An error? Not-an-error? (this recalls me fuzzy > logic) In C and C++ a warning is generally not-an-error; in D a warning is generally an error. > D has no warnings. So it either: > > - stop with a compiler error > - raise an exception Yes, so D will probably call it a compile-time error. So you're safe from most subtle unsigned/signed mismatch problems, so what's the problem with unsigned? -RB |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> ha scritto nel messaggio news:a7a1j3$24cv$1@digitaldaemon.com... > "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a7a0fl$23t5$1@digitaldaemon.com... > > > They are used anyway. Every int can be used as unsigned without problems. > > In fact they are almost the same type. > > > > int i = MAX_INT + 13; // you can use the exact literal if you know it printf("%u", i); // prints out MAX_INT + 13 > > > > Using unsigned doesn't add anything to your programs. > > Using unsigned states that this value can only be positive. This gives > compiler > the opportunity to warn programmer when he tries to pass a signed value > where > function expects an unsigned argument. > > And "they are used anyway" is wrong. Haven't you ever written anything like > this? > > for (int i = 0; i < n; i++) > ... > > Now, since i is signed, n can only be as large as 0x7fffffff (because > otherwise > the loop would never get executed). If it were declared as unsigned int, the > entire range of values up to 0xffffffff can be used. > > I wonder, why use signed int where it is obviously unsigned? What benefits does it give? There were no benefits if unsignedness were supported by the language. Try to realize that unsigned doesn't exist in C/C++ (like arrays). unsigned u = MAX_INT + 100; ... ... // now i forget that u > MAX_INT some_function(..., u, ...); // this is a third-party function accepting an int ... // or a long if sizeof(int) == sizeof(long) ... Here you are passing a small negative integer instead of a big unsigned one. And this bug can also be unnoticed for years: void some_function (..., int x, ...) { ... // x isn't used some_other_func(..., x, ...); // this function accept an unsigned ... // x isn't used } Only the day that some calculations are introduced into some_function by a third party programmer your code break (actually my code broke). > > D has no warnings. So it either: > > > > - stop with a compiler error > > - raise an exception > > > > Leaving it like it is (no warning AND no error AND no exception), is not > > the right way. > > Following this logic, D should also stop with a compiler error or raise an exception when passing a float as int argument, but it doesn't. Strict type-checking has its benefits, yet I don't like it much; guess I just had got too used to C freedom in type conversions... If the truncated float is between the int range no exception is needed :-) Pascal was my first love ;-) > Exceptions are too costly to be taken seriously in such cases. Compiler error - could be, probably requiring an explicit cast. I'd prefer it to be as it is now, though (but this is just a personal point). Simply requiring an explicit cast works well in Java and in C/C++ with all warnings turned on. As D is, it doesn't raise a warning... Ciao. |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russell Borogove | "Russell Borogove" <kaleja@estarcion.com> ha scritto nel messaggio news:3C98C99A.1010403@estarcion.com... > Roberto Mariottini wrote: > > "Pavel Minayev" <evilone@omen.ru> ha scritto nel messaggio news:a79q0b$20bt$1@digitaldaemon.com... > > > >>"Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a79gcd$1rhf$1@digitaldaemon.com... > >> > >> > >>>I'm very disappointed with this. > >>>I've programmed C for more than ten years now, and C++ for nearly 10. > >>>And I NEVER use unsigneds [snip] > > I'll guess that you don't right-shift very often. :) You are right. But when I need it, I use explicit casts (I think they are worth anyway with rigth-shift). > > They are used anyway. Every int can be used as unsigned without problems. > > In fact they are almost the same type. > > > > int i = MAX_INT + 13; // you can use the exact literal if you know it > > This probably issues a warning on some or most compilers. > > > printf("%u", i); // prints out MAX_INT + 13 > > This probably issues a warning in GCC, which does printf typechecking. If a warning is not issued, that says more about printf and the varargs mechanism than about unsigned. I agree that we need a typesafe alternative to printf. > > Yes, but what's a warning? An error? Not-an-error? (this recalls me fuzzy > > logic) > > In C and C++ a warning is generally not-an-error; in D a warning is generally an error. > > > D has no warnings. So it either: > > > > - stop with a compiler error > > - raise an exception > > Yes, so D will probably call it a compile-time error. > So you're safe from most subtle unsigned/signed mismatch > problems, so what's the problem with unsigned? The problem is that, AFAIK, D doesn't raise an error. I am wrong? Ciao |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | I would not mind being forced to cast signed to unsigned or vice versa. It would prevent this entire class of errors. However I think int literals should implicitly convert if they fit within the range of the destination, no matter what type of int the destination is. I don't like having to specify suffixes to all ints ( but 16u is a handy shortcut for cast(uint)16 ). I do however value the ability to declare a signed or unsigned integer, as the situation warrants. It's a good form of self-documentation that helps people (and the compiler) know what sort of values should be used. Sean "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a7c65n$7jl$1@digitaldaemon.com... > > "Pavel Minayev" <evilone@omen.ru> ha scritto nel messaggio news:a7a1j3$24cv$1@digitaldaemon.com... > > "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a7a0fl$23t5$1@digitaldaemon.com... > > > > > They are used anyway. Every int can be used as unsigned without > problems. > > > In fact they are almost the same type. > > > > > > int i = MAX_INT + 13; // you can use the exact literal if you know it printf("%u", i); // prints out MAX_INT + 13 > > > > > > Using unsigned doesn't add anything to your programs. > > > > Using unsigned states that this value can only be positive. This gives > > compiler > > the opportunity to warn programmer when he tries to pass a signed value > > where > > function expects an unsigned argument. > > > > And "they are used anyway" is wrong. Haven't you ever written anything > like > > this? > > > > for (int i = 0; i < n; i++) > > ... > > > > Now, since i is signed, n can only be as large as 0x7fffffff (because > > otherwise > > the loop would never get executed). If it were declared as unsigned int, > the > > entire range of values up to 0xffffffff can be used. > > > > I wonder, why use signed int where it is obviously unsigned? What benefits > > does it give? > > There were no benefits if unsignedness were supported by the language. Try to realize that unsigned doesn't exist in C/C++ (like arrays). > > unsigned u = MAX_INT + 100; > ... > ... // now i forget that u > MAX_INT > some_function(..., u, ...); // this is a third-party function accepting an > int > ... // or a long if sizeof(int) == > sizeof(long) > ... > > Here you are passing a small negative integer instead of a big unsigned one. > And this bug can also be unnoticed for years: > > void some_function (..., int x, ...) > { > ... // x isn't used > some_other_func(..., x, ...); // this function accept an unsigned > ... // x isn't used > } > > Only the day that some calculations are introduced into some_function by a third party programmer your code break (actually my code broke). > > > > D has no warnings. So it either: > > > > > > - stop with a compiler error > > > - raise an exception > > > > > > Leaving it like it is (no warning AND no error AND no exception), is not > > > the right way. > > > > Following this logic, D should also stop with a compiler error or raise an > > exception when passing a float as int argument, but it doesn't. Strict type-checking has its benefits, yet I don't like it much; guess I just had got too used to C freedom in type conversions... > > If the truncated float is between the int range no exception is needed :-) Pascal was my first love ;-) > > > Exceptions are too costly to be taken seriously in such cases. Compiler error - could be, probably requiring an explicit cast. I'd prefer it to be as it is now, though (but this is just a personal point). > > Simply requiring an explicit cast works well in Java and in C/C++ with all > warnings turned on. > As D is, it doesn't raise a warning... > > Ciao. > > |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a7c65n$7jl$1@digitaldaemon.com... > There were no benefits if unsignedness were supported by the language. Try to realize that unsigned doesn't exist in C/C++ (like arrays). > > unsigned u = MAX_INT + 100; > > ... > ... // now i forget that u > MAX_INT > some_function(..., u, ...); // this is a third-party function accepting an > int > ... // or a long if sizeof(int) == > sizeof(long) > ... > > Here you are passing a small negative integer instead of a big unsigned one. This is a problem of C weak type system, not signed/unsigned ints. > And this bug can also be unnoticed for years: > > void some_function (..., int x, ...) > { > ... // x isn't used > some_other_func(..., x, ...); // this function accept an unsigned > ... // x isn't used > } This would result in a "signed to unsigned convertion" warning on most C++ compilers I've seen. > Simply requiring an explicit cast works well in Java and in C/C++ with all > warnings turned on. > As D is, it doesn't raise a warning... My point is, I could live without casts - but I understand that others might need it as a safety guarding feature. |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | "Roberto Mariottini" <rmariottini@lycosmail.com> wrote in message news:a7c6b9$7r6$1@digitaldaemon.com... > I agree that we need a typesafe alternative to printf. I'd state that we need a typesafe alternative to varargs in general. I don't see solutions other than some sort of variant (or C# value "packaging"), and paramarrays. |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | Remember my recursive solution... ? I don't know, maybe everybody thought it was awful, but it was a possible solution... -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ] |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A024B.838850E0@deming-os.org... > Remember my recursive solution... ? > > I don't know, maybe everybody thought it was awful, but it was a possible solution... Could you please remind it? |
March 21, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | You would declare a varargs function much like C, but you would not define a body for it. The D version of printf might be: char[] printf(char[], ...); The key here is that the first argument is the same type as the return value. Then you would define a series of functions that had the same name and return value, that had the same arguments, plus a single additional argument: char[] printf(char[], int); char[] printf(char[], char); char[] printf(char[], Object); char[] printf(char[], char[]); etc... The compiler would then turn a varargs call into a recursive call: D code: printf("%d: %s\n", 123, "abc"); Expanded by the compiler to be: printf(printf("%d: %s\n", 123), "abc"); Now how this would work is that the first (i.e. the innermost) call to printf, which is printf("%d: %s\n", 123) would parse the first part of the string, printing out the first format specifier (%d), according to the value given. It would also print out any additional characters after that, up to the next format specifier. Thus, this call would print out "123: " It would return whatever of the char array is left. That is, it would return the string "%s\n" Therefore, the second (outermost) call to printf would work out to the following: printf("%s\n", "abc"); This would work just like the first, printing out the properly formatted data and any trailing characters. It prints "abc\n" and returns "" Overall, the recursive printf has printed "123: abc\n" and returned "" Now, what happens if you pass the wrong type and it doesn't match the format specifier? Well, then printf throws exceptions. In some cases, an optimizer may even be able (at compile time) to look ahead enough and realize that an exception will be thrown, and issue a warning. What happens if you call a varargs function with a function of a type you don't recognize? You get a compile-time error, of course, just as if you had called the function directly with invalid arguments. What happens if you don't use all of the format specifiers? You can deal with that by adding an out {} clause to the original printf varargs declaration: char[] printf(char[], ...) out(result) { assert(result.length == 0); } Now, you can return whatever you want from each of the printf calls...but when you're done, the result returned MUST be the empty string. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ] |
March 21, 2002 [OT] Avoiding unsigned considered harmful (was Re: Unsigned) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | (This is off-topic, because it's about a C/C++ project,
but since we were just discussing unsigned, I thought
I'd share with the whole class.)
Roberto Mariottini wrote:
> I've programmed C for more than ten years now, and C++ for nearly 10.
> And I NEVER use unsigneds, for I've learnt that it is a RIDICULOUS thing,
> that took me hours of bug tracking to find.
> Don't think you'll have much code to break, thoug, because people tend to
> not use unsigneds, like I do.
Some programmer's use of signed integers instead of
unsigned just cost me half a day of work.
I am porting a game from the Playstation 2 to the
Nintendo Gamecube. It uses a custom memory manager,
as do most console games these days. Among other
requirements, the mem manager has to be able to
allocate memory aligned to any power-of-two boundary.
The code to do this looks something like this:
void* my_alloc_aligned( int size, int align )
{
void *mem;
int address;
int aligned;
mem = my_alloc( size + align );
address = (int)mem;
// note that in the case where we happen to get
// aligned memory in the first place, this appears
// to waste an alignment, but we actually have to
// leave an offset cookie before the used memory
// block, so we can't just take the original
// allocation.
aligned = address + align - (address % align);
... more housekeeping ...
}
This works on the PS2. This gives back the wrong
address on the Gamecube. The culprit is the %
operator acting on a signed number; the user memory
space on the Gamecube is mapped in the 0x80000000
and up range. The result of the mod is negative,
the block handed back to the application is in the
wrong place, and it stomps on the next mem management
tracking block.[1]
Using unsigned int throughout this function in
place of int solves the problem, and should have
been done in the first place. Of course, the memory
mapping on the Gamecube seems a questionable choice
for this very reason, but still.
Later in the day, I ran across the code:
// make sure the pointer is reasonable
ASSERT((int)pointer > 0x100000);
Fortunately, this one was easy to identify after
having solved the above.
-Russell B
[1] The compiler can't see that align is always going
to be a power of 2, so it can't convert the mod to a
mask.[2]
[2] How do you design a language in such a way as to
strongly type a variable such that it can only be a
power of two, or only divisible by 7, or only prime?
|
Copyright © 1999-2021 by the D Language Foundation