methods of accessing bytes by pointer

General FreeBASIC programming questions.
Post Reply
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Munair wrote:Usually, if we don't want a parameter to be changed, or indicate that it doesn't change, we pass it as const. But we would have to give that up if we want to access the paramter by means of pointer arithmatic, as demonstrated in this thread. It's a choice.
???
Still not well understood where is the problem.

For protecting the initial string ("foo bar"), but allowing pointer arithmetic:

Code: Select all

sub Example(p as const zstring ptr)
  print *p
  'p[0] = "z"  '' normally disallowed
  P += 4
  print *p
end sub

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

Example(strptr(t))
Example(t)
p = strptr(t)
print *p
'p[0] = "z"  '' normally disallowed
p += 4
print *p
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Why for example want to pass to a procedure a string 'byref as const string' if you want to modify it in the body of the procedure?
Instead, pass the string 'byref as string'.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

I wouldn't exactly call it a problem. There's just a trying to figure out how things work in FreeBASIC.

When translating Pascal code there are some notable differences. One important difference is Pascal's built-in type PChar, which would be translated to FreeBASIC as zstring ptr. But as you have shown, there are different possibilities when declaring a zstring ptr. One could declare a const zstring ptr a zstring const ptr or a simple zstring ptr depending on the programming needs. In Pascal this isn't necessary as the compiler is perfectly fine with a pointer to constant strings and normal strings alike using the same syntax. No matter what, the pointer is of the same type, making pointer arithmatic easy. When trying to mimic such a pointer type in FreeBASIC, type casting will be inevitable, but like I said, I'm perfectly fine with that. It's not a problem, just a figuring out what syntax to use.
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 for example want to pass to a procedure a string 'byref as const string' if you want to modify it in the body of the procedure?
Instead, pass the string 'byref as string'.
Here is a short example to show the difference (I prefer to go for the second approach):

Code: Select all

type pchar as zstring ptr

function Example1(byref s as const string) as string
	dim as const zstring ptr p1
	dim as zstring ptr p2
	dim as string result
	
	result = s
	
	' different pointer types
	p1 = strptr(s)
	p2 = strptr(result)		
	
	'...	
	return result
end function

function Example2(byref s as const string) as string
	dim as pchar p1, p2
	dim as string result
	
	result = s
	
	' same pointer types
	p1 = cast(pchar, strptr(s))
	p2 = strptr(result)		
	
	'...	
	return result
end function
caseih
Posts: 2158
Joined: Feb 26, 2007 5:32

Re: methods of accessing bytes by pointer

Post by caseih »

Somehow C and C++ have a different definition of const than FB appears to have. In C, const pointer types refer to the constant nature of the data pointed to, not the pointer itself. Furthermore const pointers in C do not have to be initialized on declaration. You are free to assign to a const pointer variable at any time, and perform pointer arithmetic. And indeed why would you not be able to do this with const pointers. Const refers to the data type that the pointer is pointing to, not the pointer itslelf. This seems a lot more logical to me how the examples here illustrate it works in FB.

I would consider FB's behavior of const pointers a bug. The following should be completely legal:

Code: Select all

dim as const zstring ptr foo

foo = @some_zstring
foo += 1
Of course any attempt to modify a dereferenced const pointer should be a syntax error.
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

caseih wrote:I would consider FB's behavior of const pointers a bug. The following should be completely legal:

Code: Select all

dim as const zstring ptr foo

foo = @some_zstring
foo += 1
It is legal:

Code: Select all

dim as zstring * 10 some_zstring = "FreeBASIC"

dim as const zstring ptr foo

foo = @some_zstring
foo += 1
foo is not a constant pointer, it is a pointer to a constant zstring.
fxm wrote:All declaration possibilities are:
- 'Zstring Ptr' : pointer to a zstring
- 'Zstring Const Ptr' : constant pointer to a zstring
- 'Const Zstring Ptr' : pointer to a constant zstring
- 'Const Zstring Const Ptr' : constant pointer to a constant zstring
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Remarks for Munair:

- Let 'type pchar as zstring ptr' be,
  • 'as const zstring ptr' declares a pointer to a constant zstring,
    'as const pchar' declares a constant pointer to a zstring.
- Other Example:

Code: Select all

function Example3(byref s as string) as string
   dim as const zstring ptr p1 = strptr(s)
   dim as zstring ptr p2 = strptr(s)
   dim as string result
   '...
'  p1[0] = "z"  '' cannot modify the zstring through p1
   p2[0] = "z"  '' can modify the zstring through p2
   '...
   return result
end function
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

I wonder if there is a real need to have a pointer not allowing to write to a const string. After all, pointers dive under the hood, so to speak. While FB's pointer behaviour may seem logical with the different declaration possibilities, it makes things more complicated than necessary; any programmer assigning pointers is supposed to know what he's doing. Moreover, since it is possible to simply override the write-protection of a const string, why bother allowing protection control to a pointer? Yet, even though this override is allowed, it results in what I would call unexpected behaviour when writing a string byte. Writing the same byte as ubyte seems ok:

Code: Select all

dim as const string s = "foo bar"
dim as const zstring ptr p1
dim as zstring ptr p2

'pointer to const string
p1 = strptr(s)

' override const
p2 = cast(zstring ptr, strptr(s))

'error, pointer knows string is const:
'p1[2] = "t" 					

'truncates string to "fot" when printing *p2
p2[2] = "t"

'inserts character: "fot bar" when printing *p2
'(*p2)[2] = asc("t")	 

print *p2 'prints "fot"       ??? (unexpected)
print s   'prints "fot bar"   (expected)
sleep
end
Ideally, a pointer would allow read/write access to memory regardless of a buffer's type. It would make things easier and wouldn't result in inconsistencies as demonstrated here.
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

'p2[2]' is a zstring, so 'p2[2] = "t"' writes a zstring from the 3rd character of the 's' string character data : the '"t"' character plus the 'chr(0)' character (the string termination character).
This 'chr(0)' character is taken into account as terminal character only when dereferencing the 'zstring ptr', not when accessing the 's' string.
(only a var-len string accepts the nul character as any other character, because the string length is set in the descriptor)
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Munair wrote:Moreover, since it is possible to simply override the write-protection of a const string, why bother allowing protection control to a pointer?
You are right, but it is really a very special case:

Code: Select all

Sub test (Byval p As Zstring Ptr)
  *p = "Y"
End Sub

Dim As Const String s = "X"
print s
'test(strptr(s))  '' not OK
test(s)           '' OK
Print s
(only an easy way for interfacing with C functions)
Munair wrote:Ideally, a pointer would allow read/write access to memory regardless of a buffer's type. It would make things easier and wouldn't result in inconsistencies as demonstrated here.
It's your opinion, it's not mine. I consider the above behavior rather like a very small exception to the rule.
Last edited by fxm on Dec 08, 2017 19:19, 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 »

fxm wrote:'p2[2]' is a zstring, so 'p2[2] = "t"' writes a zstring from the 3rd character of the 's' string character data : the '"t"' character plus the 'chr(0)' character (the string termination character).
This 'chr(0)' character is taken into account as terminal character only when dereferencing the 'zstring ptr', not when accessing the 's' string.
(only a var-len string accepts the nul character as any other character, because the string length is set in the descriptor)
Which means that the safe way - or rather the only way - to write a single byte is by ubyte when planning to dereference a 'zstring ptr'.

For example, with the current code I'm working on: (*ostr)[0] = asc("i")
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

or ostr[0] = asc("i")
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: methods of accessing bytes by pointer

Post by Munair »

fxm wrote:or ostr[0] = asc("i")
... when relying on implicit conversion.
St_W
Posts: 1627
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: methods of accessing bytes by pointer

Post by St_W »

caseih wrote:Somehow C and C++ have a different definition of const than FB appears to have. In C, const pointer types refer to the constant nature of the data pointed to, not the pointer itself. Furthermore const pointers in C do not have to be initialized on declaration. You are free to assign to a const pointer variable at any time, and perform pointer arithmetic. And indeed why would you not be able to do this with const pointers. Const refers to the data type that the pointer is pointing to, not the pointer itslelf. This seems a lot more logical to me how the examples here illustrate it works in FB.
That is not true. In C/C++ it works exactly as it works in FB: You can declare either a constant pointer or a pointer to a constant or both (or nothing).

Code: Select all

// pointer to constant int:
const int * dummy;
// constant pointer to int:
int * const dummy = 0;
// constant pointer to constant int:
const int * const dummy = 0;
So FB behaves as it should and there's no bug.

A const qualifier specifies that a pointer or value is constant. If a pointer is specified to be constant any modification is disallowed and of course this also include pointer arithmetics. If you still need to do that on a constant pointer you're very likely doing something wrong (or the pointer shouldn't be constant). Same for the constant values: If the value that a pointer points to is specified to be constant it cannot be modified. If you still want to do this you should check your code as again probably something's wrong. Casting the const types to non-const types is considered bad style as you are working around the of the intension of the const qualifiers.
fxm
Moderator
Posts: 12152
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: methods of accessing bytes by pointer

Post by fxm »

Documentation updated:
KeyPgZstring → fxm [Added note on dereferencing a 'zstring ptr' pointer as operand of the '=' operator]
Post Reply