www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - size_t + ptrdiff_t

reply Manu <turkeyman gmail.com> writes:
Okay, so it came up a couple of times, but the questions is, what are we
going to do about it?

size_t and ptrdiff_t are incomplete, and represent non-complimentary
signed/unsigned halves of the requirement.
There are TWO types needed, register size, and pointer size. Currently,
these are assumed to be the same, which is a false assumption.

I propose size_t + ssize_t should both exist, and represent the native
integer size. Also something like ptr_t, and ptrdiff_t should also exist,
and represent the size of the pointer.

Personally, I don't like the _t notation at all. It doesn't fit the rest of
the D types, but it's established, so I don't expect it can change. But we
do need the 2 missing types.

There is also the problem that there is lots of code written using the
incorrect types. Some time needs to be taken to correct phobos too I guess.
Feb 19 2012
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 14:59, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are we going
to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
signed/unsigned
 halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently, these
are assumed
 to be the same, which is a false assumption.
The whole point of size_t and ptrdiff_t is that they are integer types that span the address space. So that the size of an allocated block of memory (and consequently, the number of elements in an array) is bound to fit in a size_t, and the displacement between two memory locations is bound to fit in a ptrdiff_t. What would this "register size" type you are proposing be for, exactly? <snip>
 There is also the problem that there is lots of code written using the
incorrect types.
<snip> Like what?
Feb 19 2012
parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 17:09, Stewart Gordon <smjg_1998 yahoo.com> wrote:

 On 19/02/2012 14:59, Manu wrote:

 Okay, so it came up a couple of times, but the questions is, what are we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned
 halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed
 to be the same, which is a false assumption.
The whole point of size_t and ptrdiff_t is that they are integer types that span the address space. So that the size of an allocated block of memory (and consequently, the number of elements in an array) is bound to fit in a size_t, and the displacement between two memory locations is bound to fit in a ptrdiff_t. What would this "register size" type you are proposing be for, exactly?
You also need a type that knows the native word size of the machine, not just a pointer width. If size_t should be the pointer size, then there needs to be some other type that specifies the register width of the architecture.
 <snip>

  There is also the problem that there is lots of code written using the
 incorrect types.
<snip> Like what?
There is code that assumes size_t is the width of the pointer, and other code that assumes size_t is the width of the native int. Only one of those is correct, whichever you declare it to be, and another type needs to be invented to define the other. It is common that pointers are the same width as the int regs, but there are many architectures where it's not true.
Feb 19 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 19-02-2012 16:26, Manu wrote:
 On 19 February 2012 17:09, Stewart Gordon <smjg_1998 yahoo.com
 <mailto:smjg_1998 yahoo.com>> wrote:

     On 19/02/2012 14:59, Manu wrote:

         Okay, so it came up a couple of times, but the questions is,
         what are we going to do about it?

         size_t and ptrdiff_t are incomplete, and represent
         non-complimentary signed/unsigned
         halves of the requirement.
         There are TWO types needed, register size, and pointer size.
         Currently, these are assumed
         to be the same, which is a false assumption.


     The whole point of size_t and ptrdiff_t is that they are integer
     types that span the address space.  So that the size of an allocated
     block of memory (and consequently, the number of elements in an
     array) is bound to fit in a size_t, and the displacement between two
     memory locations is bound to fit in a ptrdiff_t.

     What would this "register size" type you are proposing be for, exactly?


 You also need a type that knows the native word size of the machine, not
 just a pointer width. If size_t should be the pointer size, then there
 needs to be some other type that specifies the register width of the
 architecture.

     <snip>

         There is also the problem that there is lots of code written
         using the incorrect types.

     <snip>

     Like what?


 There is code that assumes size_t is the width of the pointer, and other
 code that assumes size_t is the width of the native int. Only one of
 those is correct, whichever you declare it to be, and another type needs
 to be invented to define the other.
 It is common that pointers are the same width as the int regs, but there
 are many architectures where it's not true.
Also, fun fact: Even on x86, pointers aren't necessarily 32- or 64-bit wide - in kernel space. :) -- - Alex
Feb 19 2012
prev sibling next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:
 There is code that assumes size_t is the width of the pointer
When is this not true? I can only think of 16-bit far pointers.
Feb 19 2012
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Vladimir Panteleev" <vladimir thecybershadow.net> wrote in message 
news:valucopzdhxdjymkgvuq forum.dlang.org...
 On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:
 There is code that assumes size_t is the width of the pointer
When is this not true? I can only think of 16-bit far pointers.
8-bit embedded quite often has 16-bit pointers.
Feb 19 2012
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 16:07, Daniel Murphy wrote:
 "Vladimir Panteleev"<vladimir thecybershadow.net>  wrote in message
 news:valucopzdhxdjymkgvuq forum.dlang.org...
 On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:
 There is code that assumes size_t is the width of the pointer
When is this not true? I can only think of 16-bit far pointers.
8-bit embedded quite often has 16-bit pointers.
And has an 8-bit size_t? Just found the bit I read before and was trying to find again http://www.dlang.org/portability.html "Use size_t as an alias for an unsigned integral type that can span the address space. Array indices should be of type size_t." Of course, anything below 32-bit is irrelevant to D, but according to cplusplus.com size_t is defined to be the type returned by sizeof. But where it explains sizeof it doesn't state what type that is, and I don't know what the C or C++ standard says about it. Stewart.
Feb 19 2012
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 18:03, Vladimir Panteleev
<vladimir thecybershadow.net>wrote:

 On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:

 There is code that assumes size_t is the width of the pointer
When is this not true? I can only think of 16-bit far pointers.
Ignoring small embedded systems (for which it is almost always true), some that immediately come to mind: NaCl (Google Native Client) - x64 arch, 32bit pointers ... <- of immediate concern to me PPC based consoles; PS3, X360, Wii, WiiU (not released yet) - 64bit, all 32bit pointers Android, and probably iOS; 64bit ARM chips - will certainly not fork the OS to use 64bit pointers word/pointer width mismatch does happen, even if you try to argue it's uncommon, the language MUST be able to express these architectures. It's not an optional fix. Just need to name them properly, and correct existing code.
Feb 19 2012
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/19/2012 8:23 AM, Manu wrote:
 On 19 February 2012 18:03, Vladimir Panteleev <vladimir thecybershadow.net
 <mailto:vladimir thecybershadow.net>> wrote:

     On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:

         There is code that assumes size_t is the width of the pointer


     When is this not true? I can only think of 16-bit far pointers.


 Ignoring small embedded systems (for which it is almost always true), some that
 immediately come to mind:

   NaCl (Google Native Client) - x64 arch, 32bit pointers ... <- of immediate
 concern to me
   PPC based consoles; PS3, X360, Wii, WiiU (not released yet) - 64bit, all
32bit
 pointers
   Android, and probably iOS; 64bit ARM chips - will certainly not fork the OS
to
 use 64bit pointers
On these it appears that size_t will be (and should be) the pointer width.
 word/pointer width mismatch does happen, even if you try to argue it's
uncommon,
 the language MUST be able to express these architectures. It's not an optional
 fix. Just need to name them properly, and correct existing code.
What I think you're arguing for is a "most efficient" int size, which probably would be core.stdc.config.c_int, c_uint.
Feb 19 2012
prev sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sunday, 19 February 2012 at 16:23:50 UTC, Manu wrote:
 On 19 February 2012 18:03, Vladimir Panteleev
 <vladimir thecybershadow.net>wrote:

 On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:

 There is code that assumes size_t is the width of the pointer
When is this not true? I can only think of 16-bit far pointers.
word/pointer width mismatch does happen
I know there are many systems with mismatching machine word and pointer size. I asked about cases where size_t.sizeof != (void*).sizeof.
Feb 21 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 02/19/12 17:23, Manu wrote:
 On 19 February 2012 18:03, Vladimir Panteleev <vladimir thecybershadow.net
<mailto:vladimir thecybershadow.net>> wrote:
 
     On Sunday, 19 February 2012 at 15:26:27 UTC, Manu wrote:
 
         There is code that assumes size_t is the width of the pointer
 
 
     When is this not true? I can only think of 16-bit far pointers.
 
 
 Ignoring small embedded systems (for which it is almost always true), some
that immediately come to mind:
 
  NaCl (Google Native Client) - x64 arch, 32bit pointers ... <- of immediate
concern to me
  PPC based consoles; PS3, X360, Wii, WiiU (not released yet) - 64bit, all
32bit pointers
  Android, and probably iOS; 64bit ARM chips - will certainly not fork the OS
to use 64bit pointers
not to mention linux - x32 (https://sites.google.com/site/x32abi/) But 'size_t' is the size of an object -- so sizeof(size_t)==sizeof(void*) is a pretty safe assumption. It would be a bit hard to work with objects that are larger than the address space covered by the pointer... Is any of the above platforms using segmentation tricks and is sizeof(char*-char*)>sizeof(char*)? I think you mean "native_int" - something that D is missing. On 02/19/12 19:07, Timon Gehr wrote:
 Under which circumstances is it important to have a distinct type that denotes
the register size? What kind of code requires such a type? It is unportable.
eg any time you don't want to artificially restrict the size to less than the native one, not use a type wider than the hw efficiently handles or need C compatibility. Yes, you can use 'static if' and 'version' tricks, but that's inconvenient and often obfuscates the code, so you end up reinventing c_int/c_long... And that's not ideal either; having the right types [1] always predefined would be much better. On 02/19/12 18:26, Stewart Gordon wrote:
 If you want to know the size of an int, you would just use int.sizeof. 
Problem solved.
Exactly. Except doing this for D's int would be kind of pointless, wouldn't it?... With a native_int type you *can* write generic code and switch on native_int.sizeof. artur [1] ie a signed/unsigned int that is large as the CPU registers allow. [2] [2] and note that using anything smaller can result in performance degradation, if the values need to be converted to a full-width format.
Feb 19 2012
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 15:26, Manu wrote:
<snip>
 There is code that assumes size_t is the width of the pointer, and other code
that assumes
 size_t is the width of the native int.
<snip> How does it do that? Indeed, how does code rely on the concept of native int at all? Stewart.
Feb 19 2012
parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 18:31, Stewart Gordon <smjg_1998 yahoo.com> wrote:

 On 19/02/2012 15:26, Manu wrote:
 <snip>

 There is code that assumes size_t is the width of the pointer, and other
 code that assumes
 size_t is the width of the native int.
<snip> How does it do that? Indeed, how does code rely on the concept of native int at all?
You can't imagine any situation where you might want to know how big an int is? Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... Turn that question around... if you don't know the size of a native int, how do you propose you take advantage of it?
Feb 19 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 17:04, Manu wrote:
<snip>
     Indeed, how does code rely on the concept of native int at all?

 You can't imagine any situation where you might want to know how big an int is?
<snip> Hang on ... are we talking here about some "native int", or the int type? If you want to know the size of a "native int", I think you would need to know more about how the particular machine works internally in order to take advantage of it. If you want to know the size of an int, you would just use int.sizeof. Problem solved. Stewart.
Feb 19 2012
parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 19:26, Stewart Gordon <smjg_1998 yahoo.com> wrote:

 On 19/02/2012 17:04, Manu wrote:
 <snip>

    Indeed, how does code rely on the concept of native int at all?

 You can't imagine any situation where you might want to know how big an
 int is?
<snip> Hang on ... are we talking here about some "native int", or the int type? If you want to know the size of a "native int", I think you would need to know more about how the particular machine works internally in order to take advantage of it.
In many cases you wouldn't need to know anything other than that. I don't really understand your resistance? I'm going to have the type when I need it, the question is, will it be standardised, or will I (& everyone else) invent the name and introduce a block of (probably not very portable) version() bullshit at the top of their module? Almost nobody here puts any thought towards portability, or any architecture other than x86+linux. I don't trust individuals writing their own version mess to define it correctly in their libraries... or to do it at all for that matter, they'll just be writing less portable code. Try this: Build phobos for x64, but define size_t as 32bits, and see what happens. You'll see what I'm talking about.
Feb 19 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 17:51, Manu wrote:
<snip>
     Hang on ... are we talking here about some "native int", or the int type?
<snip>
 I don't really understand your resistance? I'm going to have the type when I
need it, the
 question is, will it be standardised, or will I (& everyone else) invent the
name and
 introduce a block of (probably not very portable) version() bullshit at the
top of their
 module?
I'm not saying we shouldn't have native integer types in D. Maybe what's needed is to be clearer on what's meant exactly by a native integer type. And then add the types to Phobos/druntime. I particularly don't understand your suggestion of the names "size_t" and "ssize_t" for these types. They don't seem to me to denote the size of anything. I guess "nativeInt" and "nativeUint", defined in whatever module would be suitable, would be one possibility. Maybe someone has a better idea. But knowing what code in Phobos/druntime should be using native integer types might help put the problem in better perspective. Stewart.
Feb 19 2012
parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 23:16, Stewart Gordon <smjg_1998 yahoo.com> wrote:

 On 19/02/2012 17:51, Manu wrote:
 <snip>

    Hang on ... are we talking here about some "native int", or the int
 type?
<snip> I don't really understand your resistance? I'm going to have the type
 when I need it, the
 question is, will it be standardised, or will I (& everyone else) invent
 the name and
 introduce a block of (probably not very portable) version() bullshit at
 the top of their
 module?
I'm not saying we shouldn't have native integer types in D. Maybe what's needed is to be clearer on what's meant exactly by a native integer type. And then add the types to Phobos/druntime. I particularly don't understand your suggestion of the names "size_t" and "ssize_t" for these types. They don't seem to me to denote the size of anything. I guess "nativeInt" and "nativeUint", defined in whatever module would be suitable, would be one possibility. Maybe someone has a better idea.
well ssize_t is an already established compliment to size_t, I guess it's identical to ptrdiff_t, but some CRT's seem to prefer the ssize_t name. Personally size_t and ssize_t make more sense to me than size_t and ptrdiff_t, which seems like a contradiction of terminology, although the 'ptr' name seems more fitting to what it actually is... Ultimately I don't care, I suspect the prior commitment to size_t and ptrdiff_t can not be changed (although redefining their meaning would not be a breaking change, it just might show some cases of inappropriate usages) I agree that nativeInt should probably be in the standard library, but I'm really not into that name. It's really long and ugly. That said, I basically hate size_t too, it doesn't seem very D-ish, reeks of C mischief... and C stuffs up those types so much. It's not dependable what they actually mean in C (ie. ptr size/native word size) on all compilers I've come in contact with :/
 But knowing what code in Phobos/druntime should be using native integer
 types might help put the problem in better perspective.

 Stewart.
Feb 19 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/19/2012 3:15 PM, Manu wrote:
 Ultimately I don't care, I suspect the prior commitment to size_t and ptrdiff_t
 can not be changed (although redefining their meaning would not be a breaking
 change, it just might show some cases of inappropriate usages)
 I agree that nativeInt should probably be in the standard library, but I'm
 really not into that name. It's really long and ugly. That said, I basically
 hate size_t too, it doesn't seem very D-ish, reeks of C mischief... and C
stuffs
 up those types so much. It's not dependable what they actually mean in C (ie.
 ptr size/native word size) on all compilers I've come in contact with :/
I really think that simply adding c_int and c_uint to core.stdc.config will solve the issue. After all, is there any case where the corresponding C int type would be different from a nativeInt?
Feb 19 2012
next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 02/20/12 01:48, Walter Bright wrote:
 On 2/19/2012 3:15 PM, Manu wrote:
 Ultimately I don't care, I suspect the prior commitment to size_t and ptrdiff_t
 can not be changed (although redefining their meaning would not be a breaking
 change, it just might show some cases of inappropriate usages)
 I agree that nativeInt should probably be in the standard library, but I'm
 really not into that name. It's really long and ugly. That said, I basically
 hate size_t too, it doesn't seem very D-ish, reeks of C mischief... and C
stuffs
 up those types so much. It's not dependable what they actually mean in C (ie.
 ptr size/native word size) on all compilers I've come in contact with :/
I really think that simply adding c_int and c_uint to core.stdc.config will solve the issue. After all, is there any case where the corresponding C int type would be different from a nativeInt?
64bit platforms, depending on the definition of nativeInt. I'm not sure what it should map to, but 'widestInt' seems to be the result asked for in this thread. But would that really be different from c_long? artur
Feb 19 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 20 February 2012 02:48, Walter Bright <newshound2 digitalmars.com> wrote:

 On 2/19/2012 3:15 PM, Manu wrote:

 Ultimately I don't care, I suspect the prior commitment to size_t and
 ptrdiff_t
 can not be changed (although redefining their meaning would not be a
 breaking
 change, it just might show some cases of inappropriate usages)
 I agree that nativeInt should probably be in the standard library, but I'm
 really not into that name. It's really long and ugly. That said, I
 basically
 hate size_t too, it doesn't seem very D-ish, reeks of C mischief... and C
 stuffs
 up those types so much. It's not dependable what they actually mean in C
 (ie.
 ptr size/native word size) on all compilers I've come in contact with :/
I really think that simply adding c_int and c_uint to core.stdc.config will solve the issue. After all, is there any case where the corresponding C int type would be different from a nativeInt?
? I must have misunderstood something... I've never seen a 64bit C compiler where 'int' is 64bits.
Feb 20 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/20/2012 3:02 AM, Manu wrote:
 ? I must have misunderstood something... I've never seen a 64bit C compiler
 where 'int' is 64bits.
What are you using in C code for a most efficient integer type?
Feb 20 2012
next sibling parent reply Manu <turkeyman gmail.com> writes:
On 20 February 2012 13:16, Walter Bright <newshound2 digitalmars.com> wrote:

 On 2/20/2012 3:02 AM, Manu wrote:

 ? I must have misunderstood something... I've never seen a 64bit C
 compiler
 where 'int' is 64bits.
What are you using in C code for a most efficient integer type?
#ifdef. No 2 C compilers ever seem to agree. It's a major problem in C, hence bringing it up here. Even size_t is often broken in C. I have worked on 64bit systems with 32bit pointers where size_t was still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe my memory fails me) I want to be confident when I declare a numeric type that can interact with pointers, and also when I want the native type.
Feb 20 2012
next sibling parent reply "Regan Heath" <regan netmail.co.nz> writes:
On Mon, 20 Feb 2012 11:28:44 -0000, Manu <turkeyman gmail.com> wrote:

 On 20 February 2012 13:16, Walter Bright <newshound2 digitalmars.com>  
 wrote:

 On 2/20/2012 3:02 AM, Manu wrote:

 ? I must have misunderstood something... I've never seen a 64bit C
 compiler
 where 'int' is 64bits.
What are you using in C code for a most efficient integer type?
#ifdef. No 2 C compilers ever seem to agree. It's a major problem in C, hence bringing it up here. Even size_t is often broken in C. I have worked on 64bit systems with 32bit pointers where size_t was still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe my memory fails me) I want to be confident when I declare a numeric type that can interact with pointers, and also when I want the native type.
I can imagine situations where you want to explicitly have a numeric type that can hold/interact with pointers, or you need /more/ width than the native/efficient int type. But, in /all/ other cases surely we want the **compiler** to pick/use the native/most efficient int type/size. Further, why should we state this explicitly, why shouldn't "int" just /be/ the native/most efficient type (as determined by the compiler during compilation of each/every block of code)... I know, I know, this goes in the face of one of D's initial design decisions - being sure of the width of your types without having to guess or dig in headers for defines etc.. but, remind me why this is a bad idea? Because, it just seems to me that we want "int" to be the native/most efficient type and we want fixed sized types for special/specific cases (like in struct definitions where alignment/size matters, etc), i.e. int a; // native/efficient type int16 b; // 16 bit int int32 c; // 32 bit int int64 d; // 64 bit int ..and so on.. But.. assuming that's not going to change any time soon, we might be able to go the other way. What if we had a built-in "nint" type, which we could use everywhere we didn't care about integer type width, which resulted in the compiler picking the most efficient/native int width on a case by case basis (code inspection, etc.. not sure of the limits of this). Regan -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Feb 20 2012
parent Kevin Cox <kevincox.ca gmail.com> writes:
What if te compiler was allowed to optimist to larger types?  The only
issue is if pulled rely on overflowing.  That could be fixed by add in a
type with a minimum size specified.  This is kind of like C's fast int type.
On Feb 20, 2012 8:20 AM, "Regan Heath" <regan netmail.co.nz> wrote:

 On Mon, 20 Feb 2012 11:28:44 -0000, Manu <turkeyman gmail.com> wrote:

  On 20 February 2012 13:16, Walter Bright <newshound2 digitalmars.com>
 wrote:

  On 2/20/2012 3:02 AM, Manu wrote:
  ? I must have misunderstood something... I've never seen a 64bit C
 compiler
 where 'int' is 64bits.
What are you using in C code for a most efficient integer type?
#ifdef. No 2 C compilers ever seem to agree. It's a major problem in C, hence bringing it up here. Even size_t is often broken in C. I have worked on 64bit systems with 32bit pointers where size_t was still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe my memory fails me) I want to be confident when I declare a numeric type that can interact with pointers, and also when I want the native type.
I can imagine situations where you want to explicitly have a numeric type that can hold/interact with pointers, or you need /more/ width than the native/efficient int type. But, in /all/ other cases surely we want the **compiler** to pick/use the native/most efficient int type/size. Further, why should we state this explicitly, why shouldn't "int" just /be/ the native/most efficient type (as determined by the compiler during compilation of each/every block of code)... I know, I know, this goes in the face of one of D's initial design decisions - being sure of the width of your types without having to guess or dig in headers for defines etc.. but, remind me why this is a bad idea? Because, it just seems to me that we want "int" to be the native/most efficient type and we want fixed sized types for special/specific cases (like in struct definitions where alignment/size matters, etc), i.e. int a; // native/efficient type int16 b; // 16 bit int int32 c; // 32 bit int int64 d; // 64 bit int ..and so on.. But.. assuming that's not going to change any time soon, we might be able to go the other way. What if we had a built-in "nint" type, which we could use everywhere we didn't care about integer type width, which resulted in the compiler picking the most efficient/native int width on a case by case basis (code inspection, etc.. not sure of the limits of this). Regan -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Feb 20 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/20/2012 3:28 AM, Manu wrote:
 Even size_t is often
 broken in C. I have worked on 64bit systems with 32bit pointers where size_t
was
 still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe my
 memory fails me)
I don't know how that could be considered C standard compliant.
 I want to be confident when I declare a numeric type that can interact with
 pointers, and also when I want the native type.
I think you're probably best off for now by doing your own alias for it.
Feb 20 2012
next sibling parent James Miller <james aatch.net> writes:
On 21 February 2012 12:22, Walter Bright <newshound2 digitalmars.com> wrote:
 On 2/20/2012 3:28 AM, Manu wrote:
 Even size_t is often
 broken in C. I have worked on 64bit systems with 32bit pointers where
 size_t was
 still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe
 my
 memory fails me)
I don't know how that could be considered C standard compliant.
 I want to be confident when I declare a numeric type that can interact
 with
 pointers, and also when I want the native type.
I think you're probably best off for now by doing your own alias for it.
I don't know much about what is considered 'standard C', non x86 platforms or the intricacies of native types, so I would like some clarification on the argument going on here. AFAICT, The problem is that size_t is assumed to be the both the size of the pointer and the size of the native int, but sometimes the native int isn't the same as the size of the pointer? So you can have 64bit native ints and 32bit pointers (and maybe even vice-versa)? I also saw reference to register sizes, which I assumed, but am now guessing to be wrong, were the same size as pointers. So the problem seems to be that there are the following things that are all different sizes: * fixed int (32 bit) * native int * pointer * register But some types are conflating them? The argument seems to be confusing me because it jumps rapidly from talking about different processors to different OSes to the C standard. If the only problem is that we need some more types, can't we add them in? I don't see the problem with having verbose, import-only names for things outside the norm, alias them if you want, longer names are better for newcomers. For example, what is ptrdiff_t? I have never seen that before, and the name doesn't help me, from the alias in druntime, it seems to be the type that represents the difference between 2 pointers. Help me out here, what on earth would I use that for? (On a side note to that, no way is ssize_t a good name, ever, forwards and backwards, what on earth is it? super-size_t? here to save you? shady-size_t? you have to make sure it doesn't sell you drugs? size-size_t? it has a stammer?) I also saw a lot of talk about C compilers that don't do the right thing, is that relevant? (I mean that sincerely, not criticism)
Feb 20 2012
prev sibling next sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 02/21/12 04:12, James Miller wrote:
 If the only problem is that we need some more types, can't we add them
 in? I don't see the problem with having verbose, import-only names for
 things outside the norm, alias them if you want, longer names are
 better for newcomers. For example, what is ptrdiff_t? I have never
 seen that before, and the name doesn't help me, from the alias in
 druntime, it seems to be the type that represents the difference
 between 2 pointers. Help me out here, what on earth would I use that
 for?
In C, for storing the result of (a-b), where a and b are pointers.
 (On a side note to that, no way is ssize_t a good name, ever, forwards
 and backwards, what on earth is it? super-size_t? here to save you?
 shady-size_t? you have to make sure it doesn't sell you drugs?
 size-size_t? it has a stammer?)
It's signed, unlike the unsigned 'size_t'. Types like ptrdiff_t are not necessary in D, because you can write portable code using 'auto' and 'typeof()' - std C didn't have these, so a type had to be invented for everything. D only lacks the 'native' types; while you can, in most cases, find them out using import and version(), the compiler obviously already knows what they are for every supported target. So it's just about exposing them to the compiled code in a std, defined way. The 'C' types are only needed for interoperability, for example - the glib bindings needed these:
 import core.stdc.limits: c_long, c_ulong;
 alias  int c_int;  // Assumes 32-bit wide int.
 alias uint c_uint; // Assumes 32-bit wide int.
 import core.sys.posix.sys.types : time_t, ssize_t;
IIRC I did not find the C int types conveniently defined anywhere and didn't want to use GCC extensions. ssize_t is std and common enough that it could live outside that sys.posix module. Maybe this is also true for time_t and a few others that weren't needed in this case. artur
Feb 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 1:03 AM, Artur Skawina wrote:
 Types like ptrdiff_t are not necessary in D, because you can write portable
 code using 'auto' and 'typeof()' - std C didn't have these, so a type had
 to be invented for everything.
And, in fact, object.di contains: alias typeof(int.sizeof) size_t; alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
Feb 21 2012
parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 22 February 2012 02:19, Walter Bright <newshound2 digitalmars.com> wrote=
:
 On 2/21/2012 1:03 AM, Artur Skawina wrote:
 Types like ptrdiff_t are not necessary in D, because you can write
 portable
 code using 'auto' and 'typeof()' - std C didn't have these, so a type ha=
d
 to be invented for everything.
And, in fact, object.di contains: alias typeof(int.sizeof) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0size_t; alias typeof(cast(void*)0 - cast(void*)0) =A0 ptrdiff_t;
But as far as I can see, size_t and ptrdiff_t have a special meaning inside the compiler, and you can change their alias at will (though I've never tried). --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Feb 21 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 21 February 2012 01:22, Walter Bright <newshound2 digitalmars.com> wrote:

 On 2/20/2012 3:28 AM, Manu wrote:

 Even size_t is often
 broken in C. I have worked on 64bit systems with 32bit pointers where
 size_t was
 still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but maybe
 my
 memory fails me)
I don't know how that could be considered C standard compliant.
I don't know about you, but I very rarely get to work with a C compiler that is 'standards compliant'.. that concept is kinda like a cruel joke in my experience. Does one even exist? :) I would like to have seen size_t and ptrdiff_t (and friends) also live in core.stdc... and D define and implement its own strictly compliant concepts. As is, any GDC build will have those types defined exactly as in the C compiler... broken or not, and since they're used to interact with C code, it can't be any other way. I want to be confident when I declare a numeric type that can interact with
 pointers, and also when I want the native type.
I think you're probably best off for now by doing your own alias for it.
Fair enough I guess. Consider it though. I really don't want to rely on core.stdc; that idea makes me feel very uneasy, considering how badly C stuffs all this stuff up. I also don't want to have to import something to access the most basic of types.
Feb 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 12:33 AM, Manu wrote:
 On 21 February 2012 01:22, Walter Bright <newshound2 digitalmars.com
 <mailto:newshound2 digitalmars.com>> wrote:

     On 2/20/2012 3:28 AM, Manu wrote:

         Even size_t is often
         broken in C. I have worked on 64bit systems with 32bit pointers where
         size_t was
         still 64bit, but ptrdiff_t was 32bit (I think PS3 is like this, but
maybe my
         memory fails me)


     I don't know how that could be considered C standard compliant.


 I don't know about you, but I very rarely get to work with a C compiler that is
 'standards compliant'.. that concept is kinda like a cruel joke in my
 experience. Does one even exist? :)
The C99 Standard sez: "The types are ptrdiff_t which is the signed integer type of the result of subtracting two pointers; size_t which is the unsigned integer type of the result of the sizeof operator;" I don't know of any excuse for getting this wrong.
Feb 21 2012
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 22/02/2012 02:23, Walter Bright wrote:
<snip>
 The C99 Standard sez:

 "The types are ptrdiff_t which is the signed integer type of the result of
subtracting two
 pointers; size_t which is the unsigned integer type of the result of the
sizeof operator;"
And what does it say about what type the sizeof operator returns? Stewart.
Feb 22 2012
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Feb 20, 2012, at 3:16 AM, Walter Bright wrote:

 On 2/20/2012 3:02 AM, Manu wrote:
 ? I must have misunderstood something... I've never seen a 64bit C =
compiler
 where 'int' is 64bits.
=20 What are you using in C code for a most efficient integer type?
I can't answer for Manu, but I imagine one should probably use = int_fast32_t, etc.=
Feb 20 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-02-20 12:02, Manu wrote:
 On 20 February 2012 02:48, Walter Bright <newshound2 digitalmars.com
 <mailto:newshound2 digitalmars.com>> wrote:

     On 2/19/2012 3:15 PM, Manu wrote:

         Ultimately I don't care, I suspect the prior commitment to
         size_t and ptrdiff_t
         can not be changed (although redefining their meaning would not
         be a breaking
         change, it just might show some cases of inappropriate usages)
         I agree that nativeInt should probably be in the standard
         library, but I'm
         really not into that name. It's really long and ugly. That said,
         I basically
         hate size_t too, it doesn't seem very D-ish, reeks of C
         mischief... and C stuffs
         up those types so much. It's not dependable what they actually
         mean in C (ie.
         ptr size/native word size) on all compilers I've come in contact
         with :/


     I really think that simply adding c_int and c_uint to
     core.stdc.config will solve the issue. After all, is there any case
     where the corresponding C int type would be different from a nativeInt?


 ? I must have misunderstood something... I've never seen a 64bit C
 compiler where 'int' is 64bits.
According to Wikipedia, two out of four 64-bit data models uses 64bit integers, ILP64 and SILP64: -- /Jacob Carlborg
Feb 20 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
Feb 19 2012
next sibling parent reply Manu <turkeyman gmail.com> writes:
On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 02/19/2012 03:59 PM, Manu wrote:

 Okay, so it came up a couple of times, but the questions is, what are we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in every aspect?
Feb 19 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/19/2012 07:27 PM, Manu wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch
 <mailto:timon.gehr gmx.ch>> wrote:

     On 02/19/2012 03:59 PM, Manu wrote:

         Okay, so it came up a couple of times, but the questions is,
         what are we
         going to do about it?

         size_t and ptrdiff_t are incomplete, and represent non-complimentary
         signed/unsigned halves of the requirement.
         There are TWO types needed, register size, and pointer size.
         Currently,
         these are assumed to be the same, which is a false assumption.

         I propose size_t + ssize_t should both exist, and represent the
         native
         integer size. Also something like ptr_t, and ptrdiff_t should also
         exist, and represent the size of the pointer.

         Personally, I don't like the _t notation at all. It doesn't fit
         the rest
         of the D types, but it's established, so I don't expect it can
         change.
         But we do need the 2 missing types.

         There is also the problem that there is lots of code written
         using the
         incorrect types. Some time needs to be taken to correct phobos
         too I guess.


     Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is
     present, and what you call size_t/ssize_t does not exist. Under
     which circumstances is it important to have a distinct type that
     denotes the register size? What kind of code requires such a type?
     It is unportable.
Note that I agree that getting the terminology straight would be an overall improvement.
 It is just as unportable as size_t its self.
Currently, size_t is typeof(array.length). This is portable, and is basically the only place size_t commonly occurs in D code.
 The reason you need it is to improve portability, otherwise people need to
create arbitrary
 version mess, which will inevitably be incorrect.
 Anything from calling convention code, structure layout/packing, copying
 memory, basically optimising for 64bits at all... I can imagine static
 branches on the width of that type to select different paths.
That is not a very valid use case. In every static branch you'll know exactly what the width is.
 Even just basic efficiency, using 32bit ints on many 64bit machines
 require extra sign-extend opcodes after every single load... total waste
 of cpu time.
Using 64bit ints everywhere to represent 32bit ints won't make your program go faster. Cache lines fill up faster when the data contains large amounts of unnecessary padding. Furthermore, the compiler should be able to eliminate unneeded sign-extend operations. Anyway, extra sign-extend opcodes are not worth caring about if you get up to twice the number of conflict cache misses.
 Currently, if you're running a 64bit system with 32bit pointers, there
 is absolutely nothing that exists at compile time to tell you you're
 running a 64bit system,
Isn't there some version identifier for this? If there is not, such an identifier could be introduced trivially and this must be done.
 or to declare a variable of the machines native
 type, which you're crazy if you say is not important information.
What do you do with the machine's native type other than checking its size in a static if declaration? If you don't, then the code is unportable, and using the proper fixed size types would make it portable. If you do, then you could have checked a built-in version instead. What you effectively want for optimization is the most efficient type that is at least a certain number of bits wide. And even then, it is a moot point, because storing such variables in memory will add unnecessary padding to your data structures.
 What's the point of a 64bit machine, if you treat it exactly like a 32bit
 machine in every aspect?
There is none.
Feb 19 2012
parent Manu <turkeyman gmail.com> writes:
On 19 February 2012 21:21, Timon Gehr <timon.gehr gmx.ch> wrote:

 It is just as unportable as size_t its self.
Currently, size_t is typeof(array.length). This is portable, and is basically the only place size_t commonly occurs in D code.
What about pointer arithmetic? Interaction with C/C++ code? Writing OS level code? Hitting the hardware? And how do you define 'portable' in this context? What makes size_t more portable than a native int? A data structure containing a size_t is not 'portable' in the direct sense...
 The reason you need it is to improve portability, otherwise people need to
 create arbitrary
 version mess, which will inevitably be incorrect.
 Anything from calling convention code, structure layout/packing, copying
 memory, basically optimising for 64bits at all... I can imagine static
 branches on the width of that type to select different paths.
That is not a very valid use case. In every static branch you'll know exactly what the width is.
That's the point. Branches can each implement an efficient path for the different cases.
 Even just basic efficiency, using 32bit ints on many 64bit machines
 require extra sign-extend opcodes after every single load... total waste
 of cpu time.
Using 64bit ints everywhere to represent 32bit ints won't make your program go faster. Cache lines fill up faster when the data contains large amounts of unnecessary padding. Furthermore, the compiler should be able to eliminate unneeded sign-extend operations. Anyway, extra sign-extend opcodes are not worth caring about if you get up to twice the number of conflict cache misses.
I'm talking about the stack, passing args etc. Data structures should obviously be as tight as possible.
 Currently, if you're running a 64bit system with 32bit pointers, there
 is absolutely nothing that exists at compile time to tell you you're
 running a 64bit system,
Isn't there some version identifier for this? If there is not, such an identifier could be introduced trivially and this must be done.
Why introduce a version identifier, when a type would be so much more useful, and also neater? (usable directly rather than ugly version blocks)
 or to declare a variable of the machines native
 type, which you're crazy if you say is not important information.
What do you do with the machine's native type other than checking its size in a static if declaration? If you don't, then the code is unportable, and using the proper fixed size types would make it portable. If you do, then you could have checked a built-in version instead. What you effectively want for optimization is the most efficient type that is at least a certain number of bits wide. And even then, it is a moot point, because storing such variables in memory will add unnecessary padding to your data structures.
If that's all you do with it, then it's already proven its worth. There's a major added bonus that you could USE it... I don't like this argument that it's not portable, it's exactly as portable as size_t is already, and there's no call to remove that.
 What's the point of a 64bit machine, if you treat it exactly like a 32bit
 machine in every aspect?
There is none.
Then why do so many hardware vendors feel the need to create 64bit chips which are used in 32bit memspace platforms? It's useful to have double width registers. Some algorithms are easier with wider registers, you can move more data faster, it extends your range for intermediate values during calculations, etc. These are still real advantages, even on a 32bit memspace platform.
Feb 19 2012
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in every aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~) -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Feb 20 2012
parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 20-02-2012 09:31, Iain Buclaw wrote:
 On 19 February 2012 18:27, Manu<turkeyman gmail.com>  wrote:
 On 19 February 2012 20:07, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in every aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
IMHO, it should be. -- - Alex
Feb 20 2012
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are
we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size. Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the
rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version
mess,
 which will inevitably be incorrect.
 Anything from calling convention code, structure layout/packing, copying
 memory, basically optimising for 64bits at all... I can imagine static
 branches on the width of that type to select different paths.
 Even just basic efficiency, using 32bit ints on many 64bit machines
require
 extra sign-extend opcodes after every single load... total waste of cpu
 time.

 Currently, if you're running a 64bit system with 32bit pointers, there is
 absolutely nothing that exists at compile time to tell you you're
running a
 64bit system, or to declare a variable of the machines native type, which
 you're crazy if you say is not important information. What's the point
of a
 64bit machine, if you treat it exactly like a 32bit machine in every
aspect? gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type that represents them? :) My basic issue with these size_t/c_int/core.stdc... stuff, is that it seems the intent is to go out of the way to maintain compatibility with C, at the expense of sucking C's messy and poorly defined types into D, which is a shame. It just results in D having the same crappy archaic typing problems as C. I appreciate that the C types should exist for interoperability with C (ie, their quirks should be preserved for any given compiler/architecture), but I'd also like to see strictly defined types in D with no respect to any C counterpart, guaranteed by the language to be exactly what they claim to be, and not confused depending which compiler you try to use. These 2 GCC intrinsics would appear to be precisely what I was looking for at the start of this thread...
Feb 20 2012
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 20 February 2012 11:14, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what are
 we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size.
 Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the
 rest
 of the D types, but it's established, so I don't expect it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in every aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type that represents them? :) My basic issue with these size_t/c_int/core.stdc... stuff, is that it seems the intent is to go out of the way to maintain compatibility with C, at the expense of sucking C's messy and poorly defined types into D, which is a shame. It just results in D having the same crappy archaic typing problems as C. I appreciate that the C types should exist for interoperability with C (ie, their quirks should be preserved for any given compiler/architecture), but I'd also like to see strictly defined types in D with no respect to any C counterpart, guaranteed by the language to be exactly what they claim to be, and not confused depending which compiler you try to use. These 2 GCC intrinsics would appear to be precisely what I was looking for at the start of this thread...
Well, as Walter said, these could be aliased in core.stdc.config. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Feb 20 2012
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 20 February 2012 16:03, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 20 February 2012 11:14, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what
are
 we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size.
 Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the
native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the
 rest
 of the D types, but it's established, so I don't expect it can
change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using
the
 incorrect types. Some time needs to be taken to correct phobos too I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes
the
 register size? What kind of code requires such a type? It is
 unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing,
copying
 memory, basically optimising for 64bits at all... I can imagine static
 branches on the width of that type to select different paths.
 Even just basic efficiency, using 32bit ints on many 64bit machines
 require
 extra sign-extend opcodes after every single load... total waste of
cpu
 time.

 Currently, if you're running a 64bit system with 32bit pointers, there
 is
 absolutely nothing that exists at compile time to tell you you're
 running a
 64bit system, or to declare a variable of the machines native type,
 which
 you're crazy if you say is not important information. What's the point
 of a
 64bit machine, if you treat it exactly like a 32bit machine in every
 aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type
that
 represents them? :)

 My basic issue with these size_t/c_int/core.stdc... stuff, is that it
seems
 the intent is to go out of the way to maintain compatibility with C, at
the
 expense of sucking C's messy and poorly defined types into D, which is a
 shame. It just results in D having the same crappy archaic typing
problems
 as C.
 I appreciate that the C types should exist for interoperability with C
(ie,
 their quirks should be preserved for any given compiler/architecture),
but
 I'd also like to see strictly defined types in D with no respect to any C
 counterpart, guaranteed by the language to be exactly what they claim to
be,
 and not confused depending which compiler you try to use.

 These 2 GCC intrinsics would appear to be precisely what I was looking
for
 at the start of this thread...
Well, as Walter said, these could be aliased in core.stdc.config.
I don't think they are 'standard c' though ;)
Feb 20 2012
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 20 February 2012 16:20, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 16:03, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 20 February 2012 11:14, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what
 are
 we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent
 non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size.
 Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the
 native
 integer size. Also something like ptr_t, and ptrdiff_t should also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit the
 rest
 of the D types, but it's established, so I don't expect it can
 change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written using
 the
 incorrect types. Some time needs to be taken to correct phobos too
 I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t is present, and what you call size_t/ssize_t does not exist. Under which circumstances is it important to have a distinct type that denotes the register size? What kind of code requires such a type? It is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in every aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type that represents them? :) My basic issue with these size_t/c_int/core.stdc... stuff, is that it seems the intent is to go out of the way to maintain compatibility with C, at the expense of sucking C's messy and poorly defined types into D, which is a shame. It just results in D having the same crappy archaic typing problems as C. I appreciate that the C types should exist for interoperability with C (ie, their quirks should be preserved for any given compiler/architecture), but I'd also like to see strictly defined types in D with no respect to any C counterpart, guaranteed by the language to be exactly what they claim to be, and not confused depending which compiler you try to use. These 2 GCC intrinsics would appear to be precisely what I was looking for at the start of this thread...
Well, as Walter said, these could be aliased in core.stdc.config.
I don't think they are 'standard c' though ;)
OK, I'm just having a trudge through druntime: intptr_t and uintptr_t are guaranteed to match pointer size. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stdint.d#cl-70 c_long and c_ulong are guaranteed to match target long size (here would also go c_int and c_uint ;-). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/config.d#cl-22 This needs fixing, as wchar_t may not be same size across all targets (some change size of wchar_t based on compile time switches). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stddef.d#cl-28 This needs fixing, as wint_t may not be same size across all targets. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/wchar_.d#cl-29 -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Feb 20 2012
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 20/02/2012 17:21, Iain Buclaw wrote:
<snip>
 c_long and c_ulong are guaranteed to match target long size
<snip> Which means what, exactly? Stewart.
Feb 20 2012
next sibling parent reply Johannes Pfau <nospam example.com> writes:
Am Mon, 20 Feb 2012 17:26:53 +0000
schrieb Stewart Gordon <smjg_1998 yahoo.com>:

 On 20/02/2012 17:21, Iain Buclaw wrote:
 <snip>
 c_long and c_ulong are guaranteed to match target long size
<snip> Which means what, exactly? Stewart.
Exactly what's written there, c_long and c_ulong always match the C long/ulong types, whatever size those may be. It's mostly (only?) useful for C bindings.
Feb 20 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 20/02/2012 19:11, Johannes Pfau wrote:
<snip>
 Exactly what's written there, c_long and c_ulong always match the C
 long/ulong types, whatever size those may be. It's mostly (only?)
 useful for C bindings.
So in other words, it just means whatever somebody has decreed that the "long" keyword in C shall mean on that platform. When did C gain a type called ulong, anyway? Are we going to have c_long_long as well? Stewart.
Feb 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 2:11 PM, Stewart Gordon wrote:
 When did C gain a type called ulong, anyway?
unsigned long
 Are we going to have c_long_long as well?
Probably.
Feb 21 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-22 06:24, Walter Bright wrote:
 On 2/21/2012 2:11 PM, Stewart Gordon wrote:
 When did C gain a type called ulong, anyway?
unsigned long
 Are we going to have c_long_long as well?
Probably.
Wouldn't that always be a "long" in D? Or is it the same as with "long" in C. -- /Jacob Carlborg
Feb 21 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 22/02/2012 07:24, Jacob Carlborg wrote:
 On 2012-02-22 06:24, Walter Bright wrote:
 On 2/21/2012 2:11 PM, Stewart Gordon wrote:
<snip>
 Are we going to have c_long_long as well?
Probably.
Wouldn't that always be a "long" in D? Or is it the same as with "long" in C.
long in D is 64 bits. long in C is 32 bits (on Win16/32 at least). If the C standard sets in stone the size of a long long, then we can do away with a c_long_long and just use long. Otherwise, if we're going to have c_int and c_long, it only makes sense to have c_long_long as well. Stewart.
Feb 22 2012
parent Manu <turkeyman gmail.com> writes:
On 22 February 2012 17:16, Stewart Gordon <smjg_1998 yahoo.com> wrote:

 On 22/02/2012 07:24, Jacob Carlborg wrote:

 On 2012-02-22 06:24, Walter Bright wrote:

 On 2/21/2012 2:11 PM, Stewart Gordon wrote:
<snip>
Are we going to have c_long_long as well?

 Probably.
Wouldn't that always be a "long" in D? Or is it the same as with "long" in C.
long in D is 64 bits. long in C is 32 bits (on Win16/32 at least). If the C standard sets in stone the size of a long long, then we can do away with a c_long_long and just use long. Otherwise, if we're going to have c_int and c_long, it only makes sense to have c_long_long as well.
The C standard is completely irrelevant to D, and should not be considered. The C 'standard' is a guideline at best. I've worked with so many compilers over the years that fail, or ignore the standard in all kinds of ways. Their decisions towards the declaration of these fundamental types is a classic fuck up on lots of compilers. I can't trust anything in D defined to be "what c says".. if it's not defined and guaranteed by D, consider it as not-portable, and you'll probably need to start aliasing your own types inside super-portable libraries; version the hell out of it for every compiler you can find, just like C libs do. (Hello GLint (OpenGL), hkFloat(Havok), DWORD (windows), etc... can you think of a single super-portable library that DOESN'T redefine its primitive types?). As D cross compilers become more and more common, or other D compiler implementations begin to appear, the magnitude of the error will get more and more obvious, and also the longer it's left, the more impossible it will be to change. GDC takes its types from GCC verbatim, and they'll be every bit as broken as they would be in the corresponding C compiler. I just want D to define its types (including pointer (u)int, and native (u)int) explicitly in the D standard, and try and enforce it somehow to the tragedy never appears in D.
Feb 22 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-02-20 18:26, Stewart Gordon wrote:
 On 20/02/2012 17:21, Iain Buclaw wrote:
 <snip>
 c_long and c_ulong are guaranteed to match target long size
<snip> Which means what, exactly? Stewart.
Simplified: 32bit: Windows long == 32bit Posix long == 32bit 64bit: Windows long == 32bit Posix long == 64bit For a complete table of the 64bit data models see: -- /Jacob Carlborg
Feb 20 2012
prev sibling parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
 c_long and c_ulong are guaranteed to match target long size (here
 would also go c_int and c_uint ;-).
 https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/config.d#cl-22
That is so good! Thanks! Currently, htod translates "unsigned long" to uint, which is wrong in linux 64 bits. Translating to size_t fixes that for linux, but I fear that a C "unsigned long" is not 64bit in all 64bit systems (windows): "About size_t and ptrdiff_t" http://www.codeproject.com/Articles/60082/About-size_t-and-ptrdiff_t Ran into this problem with mysql.h: typedef st_mysql_field { ... unsigned long length; unsigned long max_length; unsigned int name_length; ... } The only adequate fix, is your c_long that matches C's long. This is because uint doesn't change when in 64bit, and size_t fixes it for linux but maybe not for windows. The C standard only guarantees that: sizeof(char) <= sizeof(int) <= sizeof(long) <= sizeof(size_t) Which is insane. At some point in history, a C int meant the native register size for fast integer operations. But now C int seems to have been frozen to 32bits to avoid struct hell. So, in conclusion, my opinion is that there is no sane way of mapping C types to D types but to use something like your c_int, c_uint, c_long, c_ulong. Otherwise, the insanity of non-standard sizes and portability never stops. Love the intptr_t! A REQUEST: how about adding a c_size_t too? --jm
Feb 21 2012
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 21 February 2012 22:45, Juan Manuel Cabo <juanmanuel.cabo gmail.com> wrote:
 A REQUEST: how about adding a c_size_t too?
Eh? -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Feb 21 2012
parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
 Eh?
All the type sizes vary in broken ways in C. The only sane way to port C structs to D is to use c_<type> that has the size of the C compiler in the target platform. If there is a single C compiler has a different sized size_t than D's, then one has achieved nothing with the c_int, c_long, etc. So that is why it'd be nice, in my opinion, to have c_size_t (and c_ssize_t) if we are going to have c_int, c_long, etc. Sorry for requesting things though!! I still don't know my way around here. --jm On 02/21/2012 08:35 PM, Iain Buclaw wrote:
 On 21 February 2012 22:45, Juan Manuel Cabo <juanmanuel.cabo gmail.com> wrote:
 A REQUEST: how about adding a c_size_t too?
Eh?
Feb 21 2012
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Feb 21, 2012, at 3:50 PM, Juan Manuel Cabo wrote:

 Eh?
=20 All the type sizes vary in broken ways in C. The only sane way to port C structs to D is to use c_<type> that has the size of the C compiler in the target platform. =20 If there is a single C compiler has a different sized size_t than D's, then one has achieved nothing with the c_int, c_long, etc. =20 So that is why it'd be nice, in my opinion, to have c_size_t (and c_ssize_t) if we are going to have c_int, c_long, etc.
size_t is intended to be the C representation. I very much do not want = to end up with a c_size_t. Are there times when D's size_t would be a = different type? Also, I wonder how much code would break if we = eliminated the size_t in object.di and replaced it with Size or = whatever.=
Feb 21 2012
parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
 size_t is intended to be the C representation.  I very much do not want to end
up with a c_size_t.
Hahah, hold your jaw because it might drop: Looking for size_t extravagancies in C, I found that VC uses __int64 for size_t in x64 target. So this behaves differently according to the target: size_t s = -2; if (s < -1) { printf("An supposedly unsigned size_t is less than -1 in x64 ??"); } else { printf("all good, size_t is still unsigned"); } Though I don't ever expect to see a VC backend for D, this shows that anything can be expected from C. If you want to keep D's size_t unsigned, then let c_size_t do whatever C does, and let D use sane types that do what the documentation says. :-) --jm On 02/21/2012 09:10 PM, Sean Kelly wrote:
 On Feb 21, 2012, at 3:50 PM, Juan Manuel Cabo wrote:
 
 Eh?
All the type sizes vary in broken ways in C. The only sane way to port C structs to D is to use c_<type> that has the size of the C compiler in the target platform. If there is a single C compiler has a different sized size_t than D's, then one has achieved nothing with the c_int, c_long, etc. So that is why it'd be nice, in my opinion, to have c_size_t (and c_ssize_t) if we are going to have c_int, c_long, etc.
size_t is intended to be the C representation. I very much do not want to end up with a c_size_t. Are there times when D's size_t would be a different type? Also, I wonder how much code would break if we eliminated the size_t in object.di and replaced it with Size or whatever.
Feb 21 2012
next sibling parent Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
I'm sorry, my snippet is wrong. It's a bit more complicated than what I first
thought, and not even uniform between VC versions:

   "size_t definition and C4267 warning"
   social.msdn.microsoft.com/forums/en-US/vclanguage/thread/62d6df45-e8e4-4bb2-87e2-b3f8e85b4b37

--jm


On 02/21/2012 09:50 PM, Juan Manuel Cabo wrote:
 size_t is intended to be the C representation.  I very much do not want to end
up with a c_size_t.
Hahah, hold your jaw because it might drop: Looking for size_t extravagancies in C, I found that VC uses __int64 for size_t in x64 target. So this behaves differently according to the target: size_t s = -2; if (s < -1) { printf("An supposedly unsigned size_t is less than -1 in x64 ??"); } else { printf("all good, size_t is still unsigned"); } Though I don't ever expect to see a VC backend for D, this shows that anything can be expected from C. If you want to keep D's size_t unsigned, then let c_size_t do whatever C does, and let D use sane types that do what the documentation says. :-) --jm On 02/21/2012 09:10 PM, Sean Kelly wrote:
 On Feb 21, 2012, at 3:50 PM, Juan Manuel Cabo wrote:

 Eh?
All the type sizes vary in broken ways in C. The only sane way to port C structs to D is to use c_<type> that has the size of the C compiler in the target platform. If there is a single C compiler has a different sized size_t than D's, then one has achieved nothing with the c_int, c_long, etc. So that is why it'd be nice, in my opinion, to have c_size_t (and c_ssize_t) if we are going to have c_int, c_long, etc.
size_t is intended to be the C representation. I very much do not want to end up with a c_size_t. Are there times when D's size_t would be a different type? Also, I wonder how much code would break if we eliminated the size_t in object.di and replaced it with Size or whatever.
Feb 21 2012
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Feb 21, 2012, at 4:50 PM, Juan Manuel Cabo wrote:

 size_t is intended to be the C representation.  I very much do not =
want to end up with a c_size_t.
=20
 Hahah, hold your jaw because it might drop:
=20
 Looking for size_t extravagancies in C, I found that VC uses __int64
 for size_t in x64 target.
I think this is actually a good thing, since working with unsigned = integers is a pain. I can't see any system needing that extra bit to = represent size any time soon anyway.=
Feb 21 2012
parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
On 02/21/2012 10:13 PM, Sean Kelly wrote:
 I think this is actually a good thing, since working with unsigned integers is
a pain.
Yes, I would prefer that msb bit to be the sign too, but behavior might depend on it, and correctness and predictability is important. My first code snippet was WRONG (sorry for the noise). And I couldn't even reproduce the problem with my VC. A correct snippet is simply this: size_t s = -2; if (s > 0) { printf("unsigned"); } else { printf("signed"); } Also, the shift operator is does a logical or arithmetic shift depending on whether it is signed or unsigned, so the result is different if you do s >> 1 whether s is signed or unsigned. THis is already nitpicky. I'm sorry for the noise. --jm
Feb 21 2012
parent Manu <turkeyman gmail.com> writes:
On 22 February 2012 03:31, Juan Manuel Cabo <juanmanuel.cabo gmail.com>wrote:

 On 02/21/2012 10:13 PM, Sean Kelly wrote:
 I think this is actually a good thing, since working with unsigned
integers is a pain. Yes, I would prefer that msb bit to be the sign too, but behavior might depend on it, and correctness and predictability is important. My first code snippet was WRONG (sorry for the noise). And I couldn't even reproduce the problem with my VC. A correct snippet is simply this: size_t s = -2; if (s > 0) { printf("unsigned"); } else { printf("signed"); } Also, the shift operator is does a logical or arithmetic shift depending on whether it is signed or unsigned, so the result is different if you do s >> 1 whether s is signed or unsigned.
Actually, it doesn't. It is not defined by C whether it should be arithmetic or logical shift right, and it is up to the compiler to choose. Microsoft's PPC compiler produces a *logical* signed shift right for instance.
Feb 22 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 4:50 PM, Juan Manuel Cabo wrote:
 Looking for size_t extravagancies in C, I found that VC uses __int64
 for size_t in x64 target.
Which is correct. size_t for 64 bit D is also a 64 bit integral type.
Feb 21 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, February 21, 2012 21:22:54 Walter Bright wrote:
 On 2/21/2012 4:50 PM, Juan Manuel Cabo wrote:
 Looking for size_t extravagancies in C, I found that VC uses __int64
 for size_t in x64 target.
Which is correct. size_t for 64 bit D is also a 64 bit integral type.
Yes, but __int64 is a signed integeral type, whereas size_t in D is an unsigned integeral type. - Jonathan M Davis
Feb 21 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 9:56 PM, Jonathan M Davis wrote:
 On Tuesday, February 21, 2012 21:22:54 Walter Bright wrote:
 On 2/21/2012 4:50 PM, Juan Manuel Cabo wrote:
 Looking for size_t extravagancies in C, I found that VC uses __int64
 for size_t in x64 target.
Which is correct. size_t for 64 bit D is also a 64 bit integral type.
Yes, but __int64 is a signed integeral type, whereas size_t in D is an unsigned integeral type.
Ah, I see.
Feb 21 2012
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 21/02/2012 22:45, Juan Manuel Cabo wrote:
<snip>
 The C standard only guarantees that:

    sizeof(char)<= sizeof(int)<= sizeof(long)<= sizeof(size_t)
<snip> I'm surprised. I'd assumed that, under 16-bit DOS/Windows, a size_t would be 16 bits. But no. Could memory blocks 64K or larger actually be allocated under those systems? Stewart.
Feb 21 2012
parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
I just went to see a standard draft
(http://www.clc-wiki.net/wiki/the_C_Standard)
to make sure, and it is even more convoluted than just that, but essentially the
same. Basically it says that chars must be at least
8bits and that shorts and ints must be able to represent at least 16 bits.

Then the ranks of the types are related to each other like that:
    rank(_Bool) < rank(char) < rank(short) < rank(int) < rank(long int) <
rank(long long int)
but rank is about conversion, not size, so while rank is strictly ordered,
sizeof types might not.

I didn't find size_t other than as the type of the value of sizeof()
expressions.

So, size_t is just standardized as the type of (sizeof(anystuff)).

I saw sizeof(long) <= sizeof(size_t)  in a website, but not on the standard.
So the standard doesn't even guarantee size_t being more than other
types, or the bigger type.

--jm


On 02/21/2012 10:23 PM, Stewart Gordon wrote:
 On 21/02/2012 22:45, Juan Manuel Cabo wrote:
 <snip>
 The C standard only guarantees that:

    sizeof(char)<= sizeof(int)<= sizeof(long)<= sizeof(size_t)
<snip> I'm surprised. I'd assumed that, under 16-bit DOS/Windows, a size_t would be 16 bits. But no. Could memory blocks 64K or larger actually be allocated under those systems? Stewart.
Feb 21 2012
parent reply Juan Manuel Cabo <juanmanuel.cabo gmail.com> writes:
 I'm surprised.  I'd assumed that, under 16-bit DOS/Windows, a size_t would
 be 16 bits. But no.  Could memory blocks 64K  or larger actually be allocated
under those systems?
size_t being the typeof sizeof() expressions, tell you the upper bound for the size of static arrays, statically allocated: sizeof(buffer)/sizeof(int) has to be representable in a size_t. It tells you nothing else. What you can allocate dinamically depends on the architecture and how it lets you address it. 16bit intel had 16bit segments and offsets, so memory was segmented and you couldn't address more than 64kb at a time. So you couldn't have grabbed^H^H"allocated" more than 64kb in real mode in intel in a single linear block. --jm
Feb 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2012 6:07 PM, Juan Manuel Cabo wrote:
 16bit intel had 16bit segments and offsets, so memory was segmented
 and you couldn't address more than 64kb at a time.
 So you couldn't have grabbed^H^H"allocated" more than 64kb in real mode in
intel
 in a single linear block.
size_t was 16 bits on all 16 bit memory models except the 'huge' one.
Feb 21 2012
parent reply Don Clugston <dac nospam.com> writes:
On 22/02/12 06:16, Walter Bright wrote:
 On 2/21/2012 6:07 PM, Juan Manuel Cabo wrote:
 16bit intel had 16bit segments and offsets, so memory was segmented
 and you couldn't address more than 64kb at a time.
 So you couldn't have grabbed^H^H"allocated" more than 64kb in real
 mode in intel
 in a single linear block.
size_t was 16 bits on all 16 bit memory models except the 'huge' one.
I expected that for ptrdiff_t, but for size_t as well? So sizeof(int *) was larger than size_t ?
Feb 22 2012
parent Manu <turkeyman gmail.com> writes:
On 22 February 2012 17:39, Don Clugston <dac nospam.com> wrote:

 On 22/02/12 06:16, Walter Bright wrote:

 On 2/21/2012 6:07 PM, Juan Manuel Cabo wrote:

 16bit intel had 16bit segments and offsets, so memory was segmented
 and you couldn't address more than 64kb at a time.
 So you couldn't have grabbed^H^H"allocated" more than 64kb in real
 mode in intel
 in a single linear block.
size_t was 16 bits on all 16 bit memory models except the 'huge' one.
I expected that for ptrdiff_t, but for size_t as well? So sizeof(int *) was larger than size_t ?
I've worked on platforms where sizeof(void*) was smaller than sizeof(size_t)
Feb 22 2012
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 20 February 2012 19:21, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 20 February 2012 16:20, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 16:03, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 20 February 2012 11:14, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions is, what
 are
 we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent
 non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer size.
 Currently,
 these are assumed to be the same, which is a false assumption.

 I propose size_t + ssize_t should both exist, and represent the
 native
 integer size. Also something like ptr_t, and ptrdiff_t should
also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It doesn't fit
the
 rest
 of the D types, but it's established, so I don't expect it can
 change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code written
using
 the
 incorrect types. Some time needs to be taken to correct phobos
too
 I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t
is
 present, and what you call size_t/ssize_t does not exist. Under
 which
 circumstances is it important to have a distinct type that denotes
 the
 register size? What kind of code requires such a type? It is
 unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in
every
 aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type that represents them? :) My basic issue with these size_t/c_int/core.stdc... stuff, is that it seems the intent is to go out of the way to maintain compatibility with C,
at
 the
 expense of sucking C's messy and poorly defined types into D, which
is a
 shame. It just results in D having the same crappy archaic typing
 problems
 as C.
 I appreciate that the C types should exist for interoperability with C
 (ie,
 their quirks should be preserved for any given compiler/architecture),
 but
 I'd also like to see strictly defined types in D with no respect to
any
 C
 counterpart, guaranteed by the language to be exactly what they claim
to
 be,
 and not confused depending which compiler you try to use.

 These 2 GCC intrinsics would appear to be precisely what I was looking
 for
 at the start of this thread...
Well, as Walter said, these could be aliased in core.stdc.config.
I don't think they are 'standard c' though ;)
OK, I'm just having a trudge through druntime: intptr_t and uintptr_t are guaranteed to match pointer size. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stdint.d#cl-70 c_long and c_ulong are guaranteed to match target long size (here would also go c_int and c_uint ;-). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/config.d#cl-22 This needs fixing, as wchar_t may not be same size across all targets (some change size of wchar_t based on compile time switches). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stddef.d#cl-28 This needs fixing, as wint_t may not be same size across all targets. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/wchar_.d#cl-29 -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
It seems the problem is already MUCH worse than in D already :( .. this was precisely my fear. Why all these redundant aliases? Just for C compatibility? Exactly one identifier for each concept should be nominated and promoted as 'standard' in D, and everyone use that same thing... The myriad of aliases may still be useful for extern(C) I suppose, but I think this is a major problem that needs careful consideration. I think one of the most insidious side effects of this problem is that programmers don't fully understand what each type is meant to represent exactly, and they accidentally select the wrong one that just appears to do the job correctly on their machine/platform at that particular moment. I'm sure this is the reason behind C compilers messing up the definition of these themselves types so frequently.
Feb 20 2012
parent Johannes Pfau <nospam example.com> writes:
Am Mon, 20 Feb 2012 21:43:31 +0200
schrieb Manu <turkeyman gmail.com>:

 On 20 February 2012 19:21, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 
 On 20 February 2012 16:20, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 16:03, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 20 February 2012 11:14, Manu <turkeyman gmail.com> wrote:
 On 20 February 2012 10:31, Iain Buclaw <ibuclaw ubuntu.com>
 wrote:
 On 19 February 2012 18:27, Manu <turkeyman gmail.com> wrote:
 On 19 February 2012 20:07, Timon Gehr <timon.gehr gmx.ch>
 wrote:
 On 02/19/2012 03:59 PM, Manu wrote:
 Okay, so it came up a couple of times, but the questions
 is, what are
 we
 going to do about it?

 size_t and ptrdiff_t are incomplete, and represent
 non-complimentary
 signed/unsigned halves of the requirement.
 There are TWO types needed, register size, and pointer
 size. Currently,
 these are assumed to be the same, which is a false
 assumption.

 I propose size_t + ssize_t should both exist, and
 represent the native
 integer size. Also something like ptr_t, and ptrdiff_t
 should
also
 exist, and represent the size of the pointer.

 Personally, I don't like the _t notation at all. It
 doesn't fit
the
 rest
 of the D types, but it's established, so I don't expect
 it can change.
 But we do need the 2 missing types.

 There is also the problem that there is lots of code
 written
using
 the
 incorrect types. Some time needs to be taken to correct
 phobos
too
 I
 guess.
Currently, size_t is defined to be what you call ptr_t, ptrdiff_t
is
 present, and what you call size_t/ssize_t does not exist.
 Under which
 circumstances is it important to have a distinct type that
 denotes the
 register size? What kind of code requires such a type? It
 is unportable.
It is just as unportable as size_t its self. The reason you need it is to improve portability, otherwise people need to create arbitrary version mess, which will inevitably be incorrect. Anything from calling convention code, structure layout/packing, copying memory, basically optimising for 64bits at all... I can imagine static branches on the width of that type to select different paths. Even just basic efficiency, using 32bit ints on many 64bit machines require extra sign-extend opcodes after every single load... total waste of cpu time. Currently, if you're running a 64bit system with 32bit pointers, there is absolutely nothing that exists at compile time to tell you you're running a 64bit system, or to declare a variable of the machines native type, which you're crazy if you say is not important information. What's the point of a 64bit machine, if you treat it exactly like a 32bit machine in
every
 aspect?
gdc offers __builtin_machine_(u)int for word size, and __builtin_pointer_(u)int for pointer size via gcc.builtins module. Nevermind though, it's not quite a "standard" :~)
That's beautiful though! Can we alias them, and produce a true D type that represents them? :) My basic issue with these size_t/c_int/core.stdc... stuff, is that it seems the intent is to go out of the way to maintain compatibility with C,
at
 the
 expense of sucking C's messy and poorly defined types into D,
 which
is a
 shame. It just results in D having the same crappy archaic
 typing problems
 as C.
 I appreciate that the C types should exist for
 interoperability with C (ie,
 their quirks should be preserved for any given
 compiler/architecture), but
 I'd also like to see strictly defined types in D with no
 respect to
any
 C
 counterpart, guaranteed by the language to be exactly what
 they claim
to
 be,
 and not confused depending which compiler you try to use.

 These 2 GCC intrinsics would appear to be precisely what I was
 looking for
 at the start of this thread...
Well, as Walter said, these could be aliased in core.stdc.config.
I don't think they are 'standard c' though ;)
OK, I'm just having a trudge through druntime: intptr_t and uintptr_t are guaranteed to match pointer size. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stdint.d#cl-70 c_long and c_ulong are guaranteed to match target long size (here would also go c_int and c_uint ;-). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/config.d#cl-22 This needs fixing, as wchar_t may not be same size across all targets (some change size of wchar_t based on compile time switches). https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stddef.d#cl-28 This needs fixing, as wint_t may not be same size across all targets. https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/wchar_.d#cl-29 -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
It seems the problem is already MUCH worse than in D already :( .. this was precisely my fear. Why all these redundant aliases? Just for C compatibility?
That's exactly what those types are for and that's the reason they're in core.stdc.* . Maybe those types shouldn't be used in normal D code, but they are necessary for C bindings.
Feb 20 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Feb 20, 2012, at 11:43 AM, Manu wrote:

 On 20 February 2012 19:21, Iain Buclaw <ibuclaw ubuntu.com> wrote:
=20
 OK, I'm just having a trudge through druntime:
=20
 intptr_t and uintptr_t are guaranteed to match pointer size.
 =
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/st= dint.d#cl-70
=20
 c_long and c_ulong are guaranteed to match target long size (here
 would also go c_int and c_uint ;-).
 =
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/co= nfig.d#cl-22
=20
 This needs fixing, as wchar_t may not be same size across all targets
 (some change size of wchar_t based on compile time switches).
 =
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/st= ddef.d#cl-28
=20
 This needs fixing, as wint_t may not be same size across all targets.
 =
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/wc= har_.d#cl-29
=20
 --
 Iain Buclaw
=20
 *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
=20
 It seems the problem is already MUCH worse than in D already :( .. =
this was precisely my fear.
 Why all these redundant aliases? Just for C compatibility?
core.stdc is an interface to the C99 API, so everything is preserved = verbatim. c_long and c_ulong were added because the size of C long = differs between Windows and non-Windows x86_64 platforms. Typically, = int, short, etc are the same however, which is why there's currently no = c_int--it was just a needless complication at the time. The aliases for = D users, if the exist at all, should be separate.=
Feb 20 2012
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 20 February 2012 21:51, Sean Kelly <sean invisibleduck.org> wrote:

 On Feb 20, 2012, at 11:43 AM, Manu wrote:

 On 20 February 2012 19:21, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 OK, I'm just having a trudge through druntime:

 intptr_t and uintptr_t are guaranteed to match pointer size.
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stdint.d#cl-70
 c_long and c_ulong are guaranteed to match target long size (here
 would also go c_int and c_uint ;-).
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/config.d#cl-22
 This needs fixing, as wchar_t may not be same size across all targets
 (some change size of wchar_t based on compile time switches).
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/stddef.d#cl-28
 This needs fixing, as wint_t may not be same size across all targets.
https://bitbucket.org/goshawk/gdc/src/87241c8e754b/d/druntime/core/stdc/wchar_.d#cl-29
 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';

 It seems the problem is already MUCH worse than in D already :( .. this
was precisely my fear.
 Why all these redundant aliases? Just for C compatibility?
core.stdc is an interface to the C99 API, so everything is preserved verbatim. c_long and c_ulong were added because the size of C long differs between Windows and non-Windows x86_64 platforms. Typically, int, short, etc are the same however, which is why there's currently no c_int--it was just a needless complication at the time. The aliases for D users, if the exist at all, should be separate.
What about intptr_t/uintptr_t, are they builtins, or in core.stdc?
Feb 20 2012
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Feb 20, 2012, at 2:34 PM, Manu wrote:
=20
 What about intptr_t/uintptr_t, are they builtins, or in core.stdc?
core.stdc. The only aliases that currently exist are defined in = object.di: alias typeof(int.sizeof) size_t; alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; alias ptrdiff_t sizediff_t; We probably need to add ssize_t at some point. Not sure about anything = more than that.=
Feb 20 2012
prev sibling parent reply kennytm <kennytm gmail.com> writes:
Manu <turkeyman gmail.com> wrote:
 I propose size_t + ssize_t should both exist, and represent the native
 integer size. 
sizediff_t (currently just aliased to ptrdiff_t but the link could be broken).
 Also something like ptr_t, and ptrdiff_t should also exist,
 and represent the size of the pointer.
 
core.stdc.stdint.uintptr_t
Feb 19 2012
next sibling parent Manu <turkeyman gmail.com> writes:
On 20 February 2012 01:10, kennytm <kennytm gmail.com> wrote:

 Manu <turkeyman gmail.com> wrote:
 I propose size_t + ssize_t should both exist, and represent the native
 integer size.
sizediff_t (currently just aliased to ptrdiff_t but the link could be broken).
 Also something like ptr_t, and ptrdiff_t should also exist,
 and represent the size of the pointer.
core.stdc.stdint.uintptr_t
O_o .. how is this different to size_t now? Why the redundant alias?
Feb 19 2012
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 02/20/12 00:17, Manu wrote:
 On 20 February 2012 01:10, kennytm <kennytm gmail.com
<mailto:kennytm gmail.com>> wrote:
 
     Manu <turkeyman gmail.com <mailto:turkeyman gmail.com>> wrote:
     > I propose size_t + ssize_t should both exist, and represent the native
     > integer size.
 
     sizediff_t (currently just aliased to ptrdiff_t but the link could be
     broken).
 
     > Also something like ptr_t, and ptrdiff_t should also exist,
     > and represent the size of the pointer.
     >
 
     core.stdc.stdint.uintptr_t
 
 
 O_o .. how is this different to size_t now? Why the redundant alias?
C compatibility? It is redundant in D, at least until it supports non-flat address spaces. :^) uintptr_t can hold a pointer, size_t only the size of something. These days there's usually not much difference, but take eg x86_16 segments - you can have several 'views' into memory, that allow for <= size_t-sized objects, but a full 'address' of such an object won't fit into a size_t. artur
Feb 19 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/02/2012 23:47, Artur Skawina wrote:
 On 02/20/12 00:17, Manu wrote:
<snip>
      core.stdc.stdint.uintptr_t

 O_o .. how is this different to size_t now? Why the redundant alias?
C compatibility?
Why would you want to use meaningless type aliases defined in the C headers in D code?
 It is redundant in D, at least  until it supports non-flat address spaces. :^)

 uintptr_t can hold a pointer,
<snip> Why would you want to do that, as opposed to use one of the pointer types (which is indeed required for GC to work correctly)? Stewart.
Feb 19 2012
parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 02/20/12 04:21, Stewart Gordon wrote:
 On 19/02/2012 23:47, Artur Skawina wrote:
 On 02/20/12 00:17, Manu wrote:
<snip>
      core.stdc.stdint.uintptr_t

 O_o .. how is this different to size_t now? Why the redundant alias?
C compatibility?
Why would you want to use meaningless type aliases defined in the C headers in D code?
C compatibility?
 uintptr_t can hold a pointer,
<snip> Why would you want to do that, as opposed to use one of the pointer types (which is indeed required for GC to work correctly)?
That's how it can be used in *C*. And the reason it needs to be exposed to D code is for interoperability with C. artur
Feb 19 2012
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 20/02/2012 03:44, Artur Skawina wrote:
<snip>
 Why would you want to do that, as opposed to use one of the pointer types
(which is
 indeed required for GC to work correctly)?
That's how it can be used in *C*. And the reason it needs to be exposed to D code is for interoperability with C.
IINM, C calling conventions care only about the size of a type, not the name or intrinsic nature of it. Therefore this is a non-issue. Stewart.
Feb 20 2012
next sibling parent Manu <turkeyman gmail.com> writes:
On 20 February 2012 20:07, Artur Skawina <art.08.09 gmail.com> wrote:

 On 02/20/12 13:32, Stewart Gordon wrote:
 On 20/02/2012 03:44, Artur Skawina wrote:
 <snip>
 Why would you want to do that, as opposed to use one of the pointer
types (which is
 indeed required for GC to work correctly)?
That's how it can be used in *C*. And the reason it needs to be exposed to D code is for interoperability
with C.
 IINM, C calling conventions care only about the size of a type, not the
name or intrinsic nature of it. Therefore this is a non-issue. struct S { uintptr_t a; }; extern (C) uintptr_t f(S* s, uintptr_t* blah); "uintptr_t" is not the best example here (because it will rarely appear in C APIs), but still shows the problem - you need to know what it is - otherwise you're left with guessing and eg assuming that uintptr==size_t. Fixing historical mistakes can be hard. There are basically three types of integer types: a) known fixed size types, such as a 32-bit wide unsigned int b) types, that are not explicitly sized, but meet certain criteria, eg: sizeof(short)<=sizeof(int)<=sizeof(long) c) externally defined types, which must always have the same representation, the above uintptr_t example falls into this category. 'C' didn't have the (a) types, so everybody had to redefine u8/s16/u32/s64 etc. 'D' added these as builtin types so that problem was solved. Unfortunately, instead of eg using the de facto std s16/s32/s64, D reused short/int/long. 'C's short/int/long were poorly (too loosely) defined, but what should have been done is defining them in 'D' as, for example: int: efficient integer type, fitting in a CPU register and at least 32 bit wide;
No, this would be very very bad. People would use 'int' out of habit in data structures, and mess up binary compatibility and alignment rules. I personally quite like D's int types as they are, but note there are some 'missing' (well, not missing, as we're discussing, but they are not well defined, or named, and needlessly aliased)
 long: efficient integer type, fitting in a CPU register and as wide as a
 GPR.
I don't think the term 'long' here, as opposed to 'int' draws this distinction... so I really can't buy into this logic.
 Fixing things up now, with for example "nativeInt" (maps to "int" above)
 and
 "widestInt" (the "long" above), is not easy. They are needed, that's why
 threads like this one appear, but simply adding them to the language or std
 library [1] wouldn't be enough. Why? Think literals, promotion and auto --
 I'm afraid programmers working with 'native' ints may not be expecting
 expressions evaluating to a narrower type.

 So there probably is no ideal simple solution for D2. For 64-bit platforms
 and
 a future D3 language, the int/long, as defined above, would be a mostly
 backward
 compatible change.
I prefer to explicitly identify these types personally. Predictable sized types are better to have people punching away with no real consideration to the specific use case. People should only use these resizing types deliberately when they know what they're doing.
 artur

 [1] fundamental types like these should not require any imports, so
 object.d
    and/or compiler is the best place for them.
Feb 20 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 02/20/12 20:50, Manu wrote:
 On 20 February 2012 20:07, Artur Skawina <art.08.09 gmail.com
<mailto:art.08.09 gmail.com>> wrote:
 
     On 02/20/12 13:32, Stewart Gordon wrote:
     > On 20/02/2012 03:44, Artur Skawina wrote:
     > <snip>
     >>> Why would you want to do that, as opposed to use one of the pointer
types (which is
     >>> indeed required for GC to work correctly)?
     >>
     >> That's how it can be used in *C*.
     >>
     >> And the reason it needs to be exposed to D code is for interoperability
with C.
     >
     > IINM, C calling conventions care only about the size of a type, not the
name or intrinsic nature of it.  Therefore this is a non-issue.
 
     struct S { uintptr_t a; };
     extern (C) uintptr_t f(S* s, uintptr_t* blah);
 
     "uintptr_t" is not the best example here (because it will rarely appear in
C
     APIs), but still shows the problem - you need to know what it is -
otherwise
     you're left with guessing and eg assuming that uintptr==size_t.
 
     Fixing historical mistakes can be hard.
 
     There are basically three types of integer types:
 
     a) known fixed size types, such as a 32-bit wide unsigned int
     b) types, that are not explicitly sized, but meet certain criteria,
         eg: sizeof(short)<=sizeof(int)<=sizeof(long)
     c) externally defined types, which must always have the same
representation,
        the above uintptr_t example falls into this category.
 
     'C' didn't have the (a) types, so everybody had to redefine u8/s16/u32/s64
etc.
     'D' added these as builtin types so that problem was solved. Unfortunately,
     instead of eg using the de facto std s16/s32/s64, D reused short/int/long.
     'C's short/int/long were poorly (too loosely) defined, but what should have
     been done is defining them in 'D' as, for example:
 
     int:  efficient integer type, fitting in a CPU register and at least 32
bit wide;
 
 
 No, this would be very very bad. People would use 'int' out of habit in data
structures, and mess up binary compatibility and alignment rules.
Explicitly sized types (ie u32 and friends) is what should be used by default in any externally visible data structures. Yes, D's attempt at redefining int and long as fixed-size integers will cause confusion. But note that the compiler could help here, by disallowing any use of int and long in aggregates not marked with an 'internal' attribute. So a relatively safe migration path might be possible.
 I personally quite like D's int types as they are, but note there are some
'missing' (well, not missing, as we're discussing, but they are not well
defined, or named, and needlessly aliased)
  
 
     long: efficient integer type, fitting in a CPU register and as wide as a
GPR.
 
 
 I don't think the term 'long' here, as opposed to 'int' draws this
distinction... so I really can't buy into this logic.
  
 
     Fixing things up now, with for example "nativeInt" (maps to "int" above)
and
     "widestInt" (the "long" above), is not easy. They are needed, that's why
     threads like this one appear, but simply adding them to the language or std
     library [1] wouldn't be enough. Why? Think literals, promotion and auto --
     I'm afraid programmers working with 'native' ints may not be expecting
     expressions evaluating to a narrower type.
 
     So there probably is no ideal simple solution for D2. For 64-bit platforms
and
     a future D3 language, the int/long, as defined above, would be a mostly
backward
     compatible change.
 
 
 I prefer to explicitly identify these types personally. Predictable sized
types are better to have people punching away with no real consideration to the
specific use case.
 People should only use these resizing types deliberately when they know what
they're doing.
I'd like to avoid using these long-named 'nativeInt' types when I know what I'm doing... ;) But, other than the 'int' and 'long' names, would such two types be enough? For D2 I'll probably end up aliasing them to something like rint/urint and wint/uwint anyway; short-term the question is only how to reliably find the alias source. artur
Feb 20 2012