www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Pointers- Confused and hating them

reply Alan Smith <alanrogersmith gmail.com> writes:
Hello everyone!

I am trying to create a cleaner version of dstring. My version, like the
original, uses an union to store the string.

union
{
 char* _cptr;
 wchar* _wptr;
 dchar* _dptr;
}

I tried to transition from Objective-C to C++ so I could write cross-platform
code. Objective-C can use pointers but I didn't ever need to. Now that I am
trying to duplicate the small size of dstring with pointers, the way dstring
does it, I'm getting lost. There are a couple things I need to know about using
unions and pointers.

#1 How do I figure out which of the three members in the union are used? I
tried comparing each to null (if (_cptr !is null) return _cptr;...) but that
didn't work, they weren't null, the wrong one had a small piece of the string
in it. My test got worse and worse but now finally works. Here is one of the
ifs:

if (*_cptr !is 0)
// _cptr is the one I want

I consider that ugly and would like to know if there is a better way to do it.

#2 How do I change the pointer I'm using from the union? I want to change from
one union member to another. For example, the current string has a char[] type.
I then alter one of the characters (e.g. str[0] = '&#3424;') and so the type
needs to be changed to wchar[]. How should I do this? How should I change the
union member I am using?

Many thanks, I have been working on this all day and have done lots of archive
searching to no avail. You're help will be *greatly* appreciated!

Peace, Alan
Jan 02 2008
next sibling parent reply 0ffh <frank youknow.what.todo.interNETz> writes:
Alan Smith wrote:
 Hello everyone!
 
 I am trying to create a cleaner version of dstring. My version, like
 the original, uses an union to store the string.
 
 union { char* _cptr; wchar* _wptr; dchar* _dptr; }
 
 I tried to transition from Objective-C to C++ so I could write
 cross-platform code. Objective-C can use pointers but I didn't ever
 need to. Now that I am trying to duplicate the small size of dstring
 with pointers, the way dstring does it, I'm getting lost. There are a
 couple things I need to know about using unions and pointers.
 
 #1 How do I figure out which of the three members in the union are
 used? I tried comparing each to null (if (_cptr !is null) return
 _cptr;...) but that didn't work, they weren't null, the wrong one had
 a small piece of the string in it. My test got worse and worse but
 now finally works. Here is one of the ifs:
 
 if (*_cptr !is 0) // _cptr is the one I want
 
 I consider that ugly and would like to know if there is a better way
 to do it.

It nearly 4 am and I have found I have a tendency to write before read, but let's see: First of all, the union won't tell you which member is used. What you're doing right now is you are going by the thing the pointer points to. It's the same as ((*_cptr)!=0). That might actually work on utf-8 encoded text, if you test in order from the smallest (char) to the biggest (dchar) member.
 #2 How do I change the pointer I'm using from the union? I want to
 change from one union member to another. For example, the current
 string has a char[] type. I then alter one of the characters (e.g.
 str[0] = '&#3424;') and so the type needs to be changed to wchar[].
 How should I do this? How should I change the union member I am
 using?

All three union members are "alive" all the time, in the sense that you can assign to them and use them in any legal way. Just remember that if you assign to _one_ member in the union, you will change _all_ of them. If you want to keep track of which union member is the one you want to use you either 1) wrap the union in a struct with an enum or something telling you which member is currently "in use" or 2) judge by the data, as it seems you're doing.
 Many thanks, I have been working on this all day and have done lots
 of archive searching to no avail. You're help will be *greatly*
 appreciated!

I sure hope I could cast some light... =)
 Peace, Alan

regards, frank
Jan 02 2008
parent 0ffh <frank youknow.what.todo.interNETz> writes:
0ffh wrote:
 It nearly 4 am and I have found I have a tendency to write before read,
 but let's see: First of all, the union won't tell you which member is
 used. What you're doing right now is you are going by the thing the
 pointer points to. It's the same as ((*_cptr)!=0). That might actually
 work on utf-8 encoded text, if you test in order from the smallest
 (char) to the biggest (dchar) member.

Scratch that last sentence. I have no idea right now why that seems to work for you. =) regards, frank
Jan 02 2008
prev sibling next sibling parent Dan <murpsoft hotmail.com> writes:
Alan Smith Wrote:

 Hello everyone!

Hello Alan, welcome to programming.
 
 I am trying to create a cleaner version of dstring. My version, like the
original, uses an union to store the string.

You're creating your own to learn, or to accomplish something? Either way, the best reference is the original if you get stuck. Starting off, you're not about to face licensing issues, so DMD front-end is GPL.
 
 union
 {
  char* _cptr;
  wchar* _wptr;
  dchar* _dptr;
 }

That thing will produce one pointer, which can point to any of a char, wchar or dchar.
 I tried to transition from Objective-C to C++ so I could write cross-platform
code. 

If you're having issues with unions and pointers, don't worry about cross platform just yet unless you have to for work or something. Objective-C can use pointers but I didn't ever need to. Now that I am trying to duplicate the small size of dstring with pointers, the way dstring does it, I'm getting lost. There are a couple things I need to know about using unions and pointers.
 
 #1 How do I figure out which of the three members in the union are used? 

There's only one pointer there. All the items in a union get put in the same spot, and the size of the union is the same as the size of it's biggest item. I tried comparing each to null (if (_cptr !is null) return _cptr;...) but that didn't work, they weren't null, the wrong one had a small piece of the string in it. My test got worse and worse but now finally works. Here is one of the ifs:
 
 if (*_cptr !is 0)

That says "if the first charcode in the string isn't 0". You'll find if the first two characters are 0, you can use wchar, and if the first 4 are 0, you can use dchar.
 // _cptr is the one I want
 
 I consider that ugly and would like to know if there is a better way to do it.
 
 #2 How do I change the pointer I'm using from the union? I want to change from
one union member to another. For example, the current string has a char[] type. 

If you want to differentiate between types in a union while your program is running, you may need to enumerate the possible types and store an int with the pointer to say which one it is. (if it's 0, it's a char[], if it's 1, it's a wchar[], etc.
I then alter one of the characters (e.g. str[0] = '&#3424;') and so the type
needs to be changed to wchar[]. How should I do this? How should I change the
union member I am using?
 
 Many thanks, I have been working on this all day and have done lots of archive
searching to no avail. You're help will be *greatly* appreciated!

Good effort, m8.
 Peace, Alan

Good luck.
Jan 02 2008
prev sibling next sibling parent Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 02 Jan 2008 21:08:36 -0500, Alan Smith wrote:

 Hello everyone!
 
 I am trying to create a cleaner version of dstring ...
 
 union
 {
  char* _cptr;
  wchar* _wptr;
  dchar* _dptr;
 }

 #1 How do I figure out which of the three members in the union are used?

A union is a list of things that all share the same RAM location. In this case here, the address of _cptr, _wptr, _dptr is identical, because they are in the union. And because there are all pointers, the are all the same length. This means that you cannot use these fields to know if which one is the 'current' string type. The commonly used way of doing this is to use a struct as well as the union ... struct MyString { union { char* _cptr; wchar* _wptr; dchar* _dptr; } enum StrType {utf8, utf16, utf32}; StrType _using; } Then when you set one of the union fields, you also set '_using' to the appropriate value. eg. MyString s; char[] c; s._cptr = c.ptr; s._using = MyString.StrType.utf8; if (s._using == MyString.StrType.utf8) SomeFunc(_cptr); else if (s._using == MyString.StrType.utf16) SomeFunc(_wptr); else if (s._using == MyString.StrType.utf32) SomeFunc(_dptr);
 I tried comparing each to null ...

Because they share the same RAM location, testing one tests them all. This method will not work.
 
 if (*_cptr !is 0)
 // _cptr is the one I want
 
 I consider that ugly and would like to know if there is a better way to do it.

And dangerous. Not to be used. -- Derek (skype: derek.j.parnell) Melbourne, Australia 3/01/2008 4:09:45 PM
Jan 02 2008
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 1/3/08, Alan Smith <alanrogersmith gmail.com> wrote:
 Hello everyone!

 I am trying to create a cleaner version of dstring.

In D2.x, dstring is already an alias for invariant(dchar)[]. It's probably not wise to reuse that name.
Jan 02 2008