March 21, 2002 Re: [OT] Avoiding unsigned considered harmful (was Re: Unsigned) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Serge K | Serge K wrote: >>>// obvious solution, isn't it? ;-) >>> >>>aligned = (address + align) & ~(align-1); >>> >>Well, yes, but then, so is using "unsigned". >> > > In such situation "unsigned" cannot help compiler to replace "%" with masking... Correctness first, then performance. (I happen to know that this game doesn't do much mem allocation in midgame, also...) > It's against logic : > "<<" - left shift with zero-filling, > ">>" - right shift with sign-filling (???), > ">>>" - right shift with zero-filling (???). > Than again - I use shifts mostly for bit-twiddling. Too bad the +/- glyph isn't traditional ascii -- we could have >> for LSR and +/->> for ASR. Of course, that would look funny. -R |
March 22, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard Krehbiel | "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7dcsf$sso$1@digitaldaemon.com... > What I meant was the declared homogenous parameter type could, within it's various constructors, set up a union containing the types, and set a type ID; not that the caller of printf would have to do it. That is, you've proposed a variant. Or, better called, "value packaging" - that one C# feature that sounds rather interesting to me. |
March 22, 2002 Re: [OT] Avoiding unsigned considered harmful (was Re: Unsigned) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russell Borogove | "Russell Borogove" <kaleja@estarcion.com> ha scritto nel messaggio news:3C9A1C02.3060708@estarcion.com... > (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. [...snip code example ...] > 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] This bug has come due to failing preconditions (memory address <= MAX_INT). This is only one of the errors that can come when using non-portable code. And writing portable code is VERY difficult, even for experienced preogrammers like me and you. You are lucky that they both have 32bit integers... > Using unsigned int throughout this function in > place of int solves the problem, and should have > been done in the first place. I disagree. A cast should be used instead, IMO ;-) Yes, unsigned can be the solution, if only they were really supported... > 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. It should be: ASSERT(pointer > (pointer_type)0x100000); You are assuming that pointer representation is linear, this may not be good. Only pointer arithmethic can do the right thing. > -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] Ok, but if you are working with bits, maybe a mask is better. > [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? I don't know. Russel, I think we have the same problem. Signed and unsigned as they are in C/C++ are not typesafe, and too error-prone to use consistently. I am not against unsigneds, I'd love to have TRUE unsigneds in C/C++. But there aren't, and this is our problem. Ciao P.S.: Just curious, does anybody used signed-modulus operator for useful tasks? |
March 22, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a7ed1d$1chu$1@digitaldaemon.com... > "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7dcsf$sso$1@digitaldaemon.com... > > > What I meant was the declared homogenous parameter type could, within it's > > various constructors, set up a union containing the types, and set a type > > ID; not that the caller of printf would have to do it. > > That is, you've proposed a variant. What I've proposed is that it's really up to the programmer. When he picks the argument type, that type's constructors (which he himself has written) decide what transformation is applied to any given arguments. Are they moved into a union with an appropriate type ID? Are they converted to a common representation (this would make sense for printf; everything eventually becomes a string)? Are their binary bits copied uninterpreted? Your own constructors make these decisions. And if you pick a basic type for the argument type, then all the arguments are checked for direct compatability. (If, say, you want a varargs function that takes an arbitrary number of doubles, but no other type.) -- Richard Krehbiel, Arlington, VA, USA rich@kastle.com (work) or krehbiel3@comcast.net (personal) |
March 22, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard Krehbiel | "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7f7hn$1qf4$1@digitaldaemon.com... > What I've proposed is that it's really up to the programmer. When he picks > the argument type, that type's constructors (which he himself has written) decide what transformation is applied to any given arguments. Are they moved into a union with an appropriate type ID? Are they converted to a common representation (this would make sense for printf; everything eventually becomes a string)? Are their binary bits copied uninterpreted? Your own constructors make these decisions. Constructors aren't called automatically in D. |
March 22, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a7fmeh$22al$1@digitaldaemon.com... > "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7f7hn$1qf4$1@digitaldaemon.com... > > > What I've proposed is that it's really up to the programmer. When he > picks > > the argument type, that type's constructors (which he himself has written) > > decide what transformation is applied to any given arguments. Are they moved into a union with an appropriate type ID? Are they converted to a common representation (this would make sense for printf; everything eventually becomes a string)? Are their binary bits copied uninterpreted? > > Your own constructors make these decisions. > > Constructors aren't called automatically in D. They're not? Saying "type o = new type;" doesn't call the constructor? Are you sure? I gotta look this up... Well, according to the text in http://www.digitalmars.com/d/class.html the constructor *is* called automatically. -- Richard Krehbiel, Arlington, VA, USA rich@kastle.com (work) or krehbiel3@comcast.net (personal) |
March 22, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard Krehbiel | "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7fo73$250h$1@digitaldaemon.com... > They're not? Saying "type o = new type;" doesn't call the constructor? Are > you sure? When you write "new type", it does. But I thought you don't want to write it in vararg function calls... |
March 22, 2002 Re: [OT] Avoiding unsigned considered harmful (was Re: Unsigned) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roberto Mariottini | Roberto Mariottini wrote: > "Russell Borogove" <kaleja@estarcion.com> ha scritto nel messaggio > news:3C9A1C02.3060708@estarcion.com... > >>(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. >> > [...snip code example ...] > > This bug has come due to failing preconditions (memory address <= MAX_INT). Which was never asserted, despite the fact that, on the whole, this code is pretty heavily peppered with assertions. (This makes me skeptical of design-by-contract as a cure-all, because some assumptions are always going to be implicit rather than explicit -- not that DBC is a bad thing, far from it!) However, with unsigned integers, it just _works_, regardless of the high address bit. That makes the function more reusable, more portable. > This is only one of the errors that can come when using non-portable code. > And writing portable code is VERY difficult, even for experienced > preogrammers > like me and you. You are lucky that they both have 32bit integers... Technically, lucky that int is at least as big as pointer to the mapped memory space on both systems, and that pointers have a reasonable bit representation. It should still be at least a few more years before consoles need more than a 4GB memory space... :) Portability is relative. I just want a little bit more portability. >>Using unsigned int throughout this function in >>place of int solves the problem, and should have >>been done in the first place. >> > > I disagree. A cast should be used instead, IMO ;-) A cast to what? You can't % or & a pointer.... >>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. >> > > It should be: > > ASSERT(pointer > (pointer_type)0x100000); Yes -- but note that this only makes a difference at the machine instruction level because pointer comparisons are considered _unsigned_. Apart from, maybe, selection of registers, on most machines that have the required integer widths (and simple pointer representations, as you correctly note) the expression ((unsigned int)pointer > 0x100000) should generate the exact same instruction sequence as (pointer > (pointer_type)0x100000) > You are assuming that pointer representation is > linear, this may not be good. > Only pointer arithmethic can do the right thing. This is a politically incorrect thing for me to say, but every C implementation I've used on for the last fourteen years has had a simple, linear pointer representation[1], could hold a pointer in a long if not an int, and could accept arbitrary integers being stored into pointers without crashing until the dereference. I know "I'm not supposed to assume that those features are universal", but anyone who introduces a new architecture that doesn't work that way at this point is a fool, and old architectures that don't work that way are rare and getting rarer.[2] > Russel, I think we have the same problem. Signed and unsigned as they > are in C/C++ are not typesafe, and too error-prone to use consistently. > I am not against unsigneds, I'd love to have TRUE unsigneds in C/C++. > But there aren't, and this is our problem. Well, we'll have to agree to disagree. I don't want "true unsigneds" because they don't match the underlying machine representation. Consider that most CPUs don't know or care if the contents of a register, or memory, are signed, unsigned, or pointer -- only the compiler really knows, and it's only through the compiler's selection of instructions to apply to them that they gain an identity as one thing or another. It's ingrained in my C experience to think of casts among pointer and integer types as being bit-preserving, and between integer and floating-point types as value- preserving. I really feel that I'd rather have a separate, general facility for range-constrained values -- where you can say, not that foo is merely signed or unsigned, but that foo's acceptable range is from -60 to +6, for example, and define whether you want out of range results silently clamped, or exceptions thrown. Such a mechanism would be far more powerful, would incur performance overhead only when asked for, and wouldn't change the behavior of the signed and unsigned types that we're used to. <rant humor_through_repetition_mode=ON> Of course, with operator overloading, you could just create a range-constrained value class, complete with a virtual handle-out-of-range function that could clamp, wrap, throw an exception, or "waveshape" out of range results, without having to extend or mutate the language itself. </rant> -Russell B [1] Although the simple representation might not be the _only_ one, cf. "near", "far", "huge" on most 16-bit x86 implementations. [2] I'm aware that this is vaguely hypocritical given my original complaint. |
March 23, 2002 Re: Type-safe varargs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a7ft8d$1da3$1@digitaldaemon.com... > "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7fo73$250h$1@digitaldaemon.com... > > > They're not? Saying "type o = new type;" doesn't call the constructor? > Are > > you sure? > > When you write "new type", it does. But I thought you don't want to write it in vararg function calls... I don't want the programmer to write it, I want the compiler to generate it. So, for the function declared thus: int print(Printarg args...) { ..the caller codes precisely this: print("The answer is", i, "\n"); ...the compiler generates: Printarg _t[3]; _t[0] = new Printarg("The answer is"); _t[1] = new Printarg(i); _t[2] = new Printarg("\n"); print(_t); |
April 03, 2002 Re: Unsigned | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a7dbi4$s5l$1@digitaldaemon.com... > Anyhow, it seems like a good solution to me. Completely typesafe, with > ability > to limit range of types that could be passed to a function, rather fast, > and should be easier to implement than paramarrays (I think). > What do you think of this, Walter? It works, but it's a lot of code generated <g>. |
Copyright © 1999-2021 by the D Language Foundation