LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous (more recent) messageNext (less recent) messagePrevious (more recent) in topicNext (less recent) in topicPrevious (more recent) by same authorNext (less recent) by same authorPrevious page (September 2000, week 4)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Thu, 28 Sep 2000 14:48:57 -0500
Reply-To:     Gregg Snell <Gregg.Snell@LABONE.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Gregg Snell <Gregg.Snell@LABONE.COM>
Subject:      Re: How to reverse variables
Content-Type: text/plain; charset="iso-8859-1"

There's nothing quite like this kind of post from one of the true "masters" that reminds me of just how little I know about SAS software. Nevertheless, please keep them coming. I catch on every now and then...

Gregg P. Snell Data Savant Consulting gsnell@swbell.net

-----Original Message----- From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU]On Behalf Of Paul Dorfman Sent: Thursday, September 28, 2000 2:36 PM To: SAS-L@LISTSERV.UGA.EDU Subject: Re: How to reverse variables

Ian,

Here is an explanation how it happens in V6.12 (without an implication that this ought to be this way). First, memory length for non-array character variables is allocated as the least 4-byte multiple of the expression length. Let us look at a variable with expression length 1 created as A='1'. In memory, it has 1 'meaningful' leading byte and 3 'wasted', 'null' bytes: '1---' ('-' is for a null byte). The value of the variable is defined solely by the information residing in the meaningful byte(s). In this case, nothing moved to any of the three null bytes can change the value of the variable. If the declared length were 2, then the two remaining null bytes will have no effect. Here is a proof:

658 data _null_; 659 a = '0'; 660 call poke ('4',addr(a)+3, 1); 661 put a=; 662 call poke ('3',addr(a)+2, 1); 663 put a=; 664 call poke ('2',addr(a)+1, 1); 665 put a=; 666 call poke ('1',addr(a) , 1); 667 put a=; 668 in_mem = peekc (addr(a), 4); 669 put in_mem=; 670 run; ----------- A=0 A=0 A=0 A=1 IN_MEM=1234 -----------

As we can plainly see, the stuff I moved to the null bytes is there indeed, but only the value moved to the meaningful byte affects the value of A. Now let us get back to your example. Because the memory length for all A, B, C, D, E is 4, they are really stored in memory as

1---2---3---4---5---

It is easy to ascertain using

length in_mem $20; in_mem = translate(peekc(addr(a),20),'-',' '); put in_mem=;

If you grab 17 bytes, what you grab is exactly

1---2---3---4---5

In reverse, it is

5---4---3---2---1

When you POKE that back in memory, what you have is

5---4---3---2---1---

This move aligns '5', '4', '3', '2', '1' with each variable's meaningful byte, hence they are populated as expected. Now if you grab 18 bytes, what you grab is exactly

1---2---3---4---5-

In reverse, it becomes

-5---4---3---2---1

Moving that to memory starting with addr(a) results in (asterisks indicate meaningful bytes):

*5--*4--*3--*2--*1--

Thus, the meaningful bytes of all variables end up populated with blanks, and what resides in the null bytes, does not matter, hence the values of all variables are blank. QED.

The same exact thingie occurs with 5-byte variables, for each has the memory length 8:

11111---22222---33333---44444---55555---

The last 5 is in position 37, hence the 'magic' number. For 8-byte variables, naturally, there are no null bytes:

1111111122222222333333334444444455555555

and hence 48 is the 'magic' number.

Of course, I agree that with V8.*, there is no need to understand this mechanics, since no null bytes are allocated, but those still with V6.12 might find it useful.

Kind regards, ===================== Paul Dorfman Jacksonville, Fl =====================

>From: Ian Whitlock <WHITLOI1@WESTAT.COM> > >John, > >It is not clear to me exactly what is happening, but this code does the >reversal >in 6.12 under windows 95. > >data _null_ ; > retain a "1" b "2" c "3" d "4" e "5" ; > > call poke(reverse(peekc(addr(a),17)),addr(a),17); > put a= b= c= d= e= ; >run; > >Incidentally, if one changes the 17's to 20 all fields go blank. >Can the magic formula be > > 4 * ( n - 1 ) + 1 > >On the other hand, for 4 byte character variables > >356 data null_ ; >357 retain a "1111" b "2222" c "3333" d "4444" e "5555" ; >358 >359 call poke(reverse(peekc(addr(a),20)),addr(a),20); >360 put a= b= c= d= e= ; >361 run; > >A=5555 B=4444 C=3333 D=2222 E=1111 >NOTE: The data set WORK.NULL_ has 1 observations and 5 variables. >NOTE: The DATA statement used 0.27 seconds. > >But for 5 byte variables the magic number is 37, for 8 byte 48. >So how is character data stored in V6? Maybe more fruitful to ask >how soon you can move to V8? > >Ian Whitlock <whitloi1@westat.com> > >-----Original Message----- >From: John Whittington [mailto:John.W@MEDISCIENCE.CO.UK] >Sent: Thursday, September 28, 2000 11:43 AM >To: SAS-L@LISTSERV.UGA.EDU >Subject: Re: How to reverse variables > > >At 10:36 28/09/00 -0500, Jonathan Goldberg wrote (in part): > > >copied directly from Charles Patridge's post with SAS V8.0 under Solaris >5.6 > >gives: > > > >Obs v1 v2 v3 v4 v5 > > > > 1 5 4 3 2 1 > > > >just as Paul claimed it would. I cannot explain the discrepancy. > >It seems that while SAS v8.0 uses one byte to store a character variable of >length 1, v6.12 uses 4 bytes (even if one explicitly declares the length as >1). > >Kind Regards, > > >John > >---------------------------------------------------------------- >Dr John Whittington, Voice: +44 (0) 1296 730225 >Mediscience Services Fax: +44 (0) 1296 738893 >Twyford Manor, Twyford, E-mail: John.W@mediscience.co.uk >Buckingham MK18 4EL, UK mediscience@compuserve.com >----------------------------------------------------------------

_________________________________________________________________________ Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.

Share information about yourself, create your own public profile at http://profiles.msn.com.


Back to: Top of message | Previous page | Main SAS-L page