methods of accessing bytes by pointer

General FreeBASIC programming questions.
Post Reply
St_W
Posts: 1626
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: methods of accessing bytes by pointer

Post by St_W »

Munair wrote:That's exactly why I posted it. Not sure why it is considered spamming. :-)
I didn't say that. Probably the reason for the confustion is that the question wasn't very clear. (and MrSwiss is known to be quite direct and not very polite :-| )

If I understood it correctly, the question is why an implicit conversion from zstring to UBYTE is done for assignment, but not for the usage in SELECT CASE.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

MrSwiss wrote:
Select Case, a specific convergence to Asc is required.
No, it just requires to write the "case" differently
You seem to be missing the point.
MrSwiss wrote:
Not sure why it is considered spamming. :-)
Maybe, because you opened 7 Threads, within 48 hours ???
At least my threads are about programming and they are quite specific at that. Fxm and some others seem happy to help. In contrast, there are some off-topic threads here that IMHO would much more qualify as spam. You will never see me partake in these "discussions". You should be happy that I'm not a moderator of this forum. Pun intended.
Last edited by Munair on Dec 07, 2017 18:35, edited 1 time in total.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

St_W wrote:
Munair wrote:That's exactly why I posted it. Not sure why it is considered spamming. :-)
I didn't say that. Probably the reason for the confustion is that the question wasn't very clear. (and MrSwiss is known to be quite direct and not very polite :-| )

If I understood it correctly, the question is why an implicit conversion from zstring to UBYTE is done for assignment, but not for the usage in SELECT CASE.
Actually, it wasn't a question. See the fourth post; it was an additional observation to the question already answered by fxm.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Munair wrote:Hmm. FB seems to do funny things when reading writing bytes. When using pointers then ASC and CHR seem interchangable, at least on assignment. When accessing a string byte directly, only ASC is allowed. Consider the follwing code:

Code: Select all

dim t as string = space(3)
dim p as zstring ptr = strptr(t)
dim a as ubyte
dim c as string * 1

p[0] = "F"
p[1] = 111
p[2] = 111
print t

a = p[0] ' OK
c = p[0] ' OK

a = t[0] ' OK
c = t[0] ' NOT OK

' *** BUT ***
select case p[0]
	case &h41 to &h5A ' NOT OK
		print "caps"
end select

select case asc(p[0])
	case &h41 to &h5A '  OK
		print "caps"
end select

select case t[0]
	case &h41 to &h5A '  OK
		print "caps"
end select
end
Treating dereferenced pointers as characters and string bytes as values seems like the safe way to go.
Why search the difficulty (by using implicit conversion) when the direct syntax exists:

Code: Select all

dim t as string = space(3)
dim p as zstring ptr = strptr(t)
dim a as ubyte
dim c as string * 1

p[0] = "F"     '' p[0] is a zstring
(*p)[1] = 111  '' (*p)[1] is an ubyte
(*p)[2] = 114  '' (*p)[2] is an ubyte
print t

a = (*p)[1]  '' (*p)[1] is an ubyte
print a
c = p[1]     '' p[1] is a zstring
print c

a = t[2]  '' t[2] is an ubyte
print a
c = t     '' t is a string
print c

select case (*p)[0]  '' (*p)[0] is an ubyte
   case &h41 to &h5A
      print "caps"
end select

select case asc(p[0])  '' p[0] is a zstring
   case &h41 to &h5A
      print "caps"
end select

select case t[0]  '' t[0] is an ubyte
   case &h41 to &h5A
      print "caps"
end select
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

fxm wrote:Why search the difficulty (by using implicit conversion) when the direct syntax exists
I wasn't aware I was searching difficulty. But it would be helpful if the compiler wouldn't allow implicit conversion here, especially since it doesn't allow it with e.g. a select case statement. However, these 'difficulties' do help me to understand the FB compiler. :-)
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Let 'pz' be a 'Zstring Ptr' pointer:
When using the '=' operator (assignment or equal) and only in this case, the operand 'pz[n]' (dereferencing a Zstring Ptr) can give a 'Zstring' string or a 'Ubyte' character, depending on the other operand. If other operand is numeric, so 'pz[n]' will be treated as reference to the (n+1)th character (it's the same as '(*pz)[n]'). It'is basically a short-cut version of string indexing, and it's all.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

fxm wrote:Let 'pz' be a 'Zstring Ptr' pointer:
When using the '=' operator (assignment or equal) and only in this case, the operand 'pz[n]' (dereferencing a Zstring Ptr) can give a 'Zstring' string or a 'Ubyte' character, depending on the other operand. If other operand is numeric, so 'pz[n]' will be treated as reference to the (n+1)th character (it's the same as '(*pz)[n]'). It'is basically a short-cut version of string indexing, and it's all.
Thanks for the clarification.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

fxm wrote:Let 'pz' be a 'Zstring Ptr' pointer:
When using the '=' operator (assignment or equal) and only in this case, the any operand 'pz[n]' (dereferencing a Zstring Ptr) can give a 'Zstring' string or a 'Ubyte' character, depending on the other operand. If other operand is numeric, so 'pz[n]' will be treated as reference to the (n+1)th character (it's the same as '(*pz)[n]'). It'is basically a short-cut version of string indexing, and it's all.
I do not think this particular case deserves to be noted in the documentation, but if need I will do it (for example on the page ZSTRING).
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

fxm wrote:
fxm wrote:Let 'pz' be a 'Zstring Ptr' pointer:
When using the '=' operator (assignment or equal) and only in this case, the any operand 'pz[n]' (dereferencing a Zstring Ptr) can give a 'Zstring' string or a 'Ubyte' character, depending on the other operand. If other operand is numeric, so 'pz[n]' will be treated as reference to the (n+1)th character (it's the same as '(*pz)[n]'). It'is basically a short-cut version of string indexing, and it's all.
I do not think this particular case deserves to be noted in the documentation, but if need I will do it (for example on the page ZSTRING).
Well, it''s quite specific and definitely important to know when accessing string indices. I ran into this because Pascal allows for the same thing, except it accepts type char only; it doesn't allow implicit conversion. So with PChar (zstring ptr) P^ would be *P, or P[0] and the next would be P[n], the same notation as in FreeBASIC. Hence the confusion when I could assign a ubyte in FB. It may not be every days programming practice, but it wouldn't hurt to cover some of it in the manual.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Munair wrote:It may not be every days programming practice, but it wouldn't hurt to cover some of it in the manual.
I would like to hear from other users before adding this kind of detail note in the documentation:

This note could be added at the description paragraph end of the ZSTRING page:
.....
Note : When any operand of the '=' operator (assignment or equal) consists in dereferencing a 'Zstring Ptr' pointer ('pz'), this can give a 'Zstring' string or a 'Ubyte' character, depending on the other operand. If the other operand is numeric, so the dereferenced 'Zstring Ptr' pointer ('*pz') will be treated as a 'Ubyte' reference to the one character pointed. If a 'Zstring' pointer indexing '[]' operator is used as dereferencing syntax ('pz[n]'), it is basically a short-cut version of the 'String' indexing '[]' operator ('(*pz)[n]).
Example:

Code: Select all

Dim As Zstring * 10 z = "freebasic"
Dim As Zstring Ptr pz = @z
Dim As Ubyte b

Print *pz
*pz = 70                       '' 70=Asc("F") is numeric, *pz is treated as ubyte
pz[4] = 66                     '' 66=Asc("B") is numeric, pz[4] is treated as ubyte (short-cut version of (*pz)[4])
Print *pz                      '' *pz is treated as zstring
If pz[4] = 66 Then Print "OK"  '' 66=Asc("B") is numeric, pz[4] is treated as ubyte (short-cut version of (*pz)[4]
b = *pz                        '' b is ubyte, *pz is treated as ubyte
Print b
b = pz[4]                      '' b is ubyte, pz[4] is treated as ubyte (short-cut version of (*pz)[4])
Print b
If b = pz[4] Then Print "OK"   '' b is ubyte, pz[4] is treated as ubyte (short-cut version of (*pz)[4])

Sleep

Code: Select all

freebasic
FreeBasic
OK
70
66
OK
[edit]
- Replace 'traited' with 'treated'.
Last edited by fxm on Dec 09, 2017 6:22, edited 7 times in total.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

That would be extremely helpful IMO, as the implicit casting is not self-evident for those (relatively) new to the FB compiler. It definitely got me confused a bit. I bet there are Pascal programmers out there who use the PChar data type without realizing much what's happening under the hood. This is because FPC is more strict if it comes to implicit type casting, which is why it is relatively easy there to do pointer arithmatics. I'm happy to see that FBC allows us to do the same, but it isn't as obvious. In this respect it would be helpful to have something like this in FB:

Code: Select all

dim buffer as string
dim p as PChar  ' zstring ptr type

buffer = "something"
p = CPChar(buffer[0])  ' convert to PChar

' instead of:
p = cast(PChar, @buffer[0])
The cast construction is powerful, but it requires more thinking and it looks a bit verbose, especially when passing as parameters.

Anyway, I saved your example for future reference. (BTW 'traited' should be 'treated'.)
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

It's already simple in FreeBASIC:

Code: Select all

dim buffer as string
dim p1 as zstring ptr, p2 as zstring ptr

buffer = "something"

p1 = strptr(buffer)
'' or
p2 = @buffer[0]

print *p1
print *p2

sleep
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

Code: Select all

dim t as const string = "foo"
dim p as zstring ptr

sub Example(p as zstring ptr)
	print *p
end sub

'Example(@t[0]) ' ERROR

Example(cast(zstring ptr, @t[0]))
Not sure if the difference is covered somewhere in the documentation.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

In the above example, a simple:

Code: Select all

Example(t)
works.

In order to make calling the C runtime functions very easy, any string type argument may be directly passed to a procedure referring to a parameter declared as '[const] zstring [const] ptr'. The compiler performs itself an automatic conversion (without warning message) between string and '[const] zstring [const] ptr'.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

fxm wrote:In the above example, a simple:

Code: Select all

Example(t)
works.

In order to make calling the C runtime functions very easy, any string type argument may be directly passed to a procedure referring to a parameter declared as '[const] zstring [const] ptr'. The compiler performs itself an automatic conversion (without warning message) between string and '[const] zstring [const] ptr'.
While one can simple pass T like Example(t), explicit casting is needed when passing a specific offset, or so it seems. The following code results in a compile error "error 181: Invalid assignment/conversion, at parameter 1 (p) of EXAMPLE() in 'Example(@t[1]))'":

Code: Select all

dim t as const string = "foo"
dim p as zstring ptr

sub Example(p as zstring ptr)
	print *p
end sub

Example(@t[1]))
While it may seem trivial to some, it is a required programming technique when dealing with text encodings.
Post Reply