const parameter writeable

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

const parameter writeable

L505

Are const parameters supposed to ensure read only access?
If so how come one can write to a typed pointer?

program project1;

{$mode objfpc}{$H+}

  type
    PSomeRec = ^TSomeRec;
    TSomeRec = record
      a: string;
      b: string;
    end;

  procedure ChangeRec1(const Rec: PSomeRec);
  begin
    Rec^.a:= 'string A';
  end;

var
  RecPtr: PSomeRec;
begin
  new(RecPtr);
  ChangeRec1(RecPtr);
  writeln(RecPtr^.a);
  dispose(RecPtr);
  readln;
end.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Peter Vreman
>
> Are const parameters supposed to ensure read only access?
> If so how come one can write to a typed pointer?
>
> program project1;
>
> {$mode objfpc}{$H+}
>
>   type
>     PSomeRec = ^TSomeRec;
>     TSomeRec = record
>       a: string;
>       b: string;
>     end;
>
>   procedure ChangeRec1(const Rec: PSomeRec);
>   begin
>     Rec^.a:= 'string A';
>   end;
>
> var
>   RecPtr: PSomeRec;
> begin
>   new(RecPtr);
>   ChangeRec1(RecPtr);
>   writeln(RecPtr^.a);
>   dispose(RecPtr);
>   readln;
> end.

Only the pointer itself is the parameter and read-only. Where the pointer
points to is irrelevant.





_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Michael Müller-4
On Sat, Apr 29, 2006 at 11:20:04PM +0200, Peter Vreman <[hidden email]> wrote:

> >
> > Are const parameters supposed to ensure read only access?
> > If so how come one can write to a typed pointer?
> >
> > program project1;
> >
> > {$mode objfpc}{$H+}
> >
> >   type
> >     PSomeRec = ^TSomeRec;
> >     TSomeRec = record
> >       a: string;
> >       b: string;
> >     end;
> >
> >   procedure ChangeRec1(const Rec: PSomeRec);
> >   begin
> >     Rec^.a:= 'string A';
> >   end;
> >
> > var
> >   RecPtr: PSomeRec;
> > begin
> >   new(RecPtr);
> >   ChangeRec1(RecPtr);
> >   writeln(RecPtr^.a);
> >   dispose(RecPtr);
> >   readln;
> > end.
>
> Only the pointer itself is the parameter and read-only. Where the pointer
> points to is irrelevant.

But in this case I'm wondering why you want to give a pointer instead
of the real type?

The reason for a pointer is normally in this case to avoid that the
given data is copied into local variables.

>From my understand the compiler handles following parameter attributes:
- 'var': call by reference => gives pointers, content writable
- 'const': gives pointer, content read-only
- '': call by value => creates a local copy of the data, content is
lost after end of procedure/function
- 'out': I'm not sure if it's more similar to 'var' or ''.

This is the reason why I always declare parameters that are not 'var'
with 'const'.

Are my expanations right especially related to 'const'?

Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Moz
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Moz
Michael says:
> - 'const': gives pointer, content read-only

In practice the compiler may[1] check for access to the value at compile
time and just give you a pointer to the real thing (since it knows you
won't change it). With a non-specified parameter it has to make a copy and
pass that, which slows everything down. Especially for big parameters, and
you shouldn't pass big structs around for that reason.

Moz
[1] I assume FPC does this, but don't know for sure.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Jonas Maebe-2
In reply to this post by Michael Müller-4

On 01 May 2006, at 08:11, Michael Müller wrote:

> - 'const': gives pointer, content read-only

The compiler can handle const parameters in any way it wants, and it  
may even differ among different cpu's and calling conventions.  
Sometimes they are passed by value, sometimes by reference. It  
depends on what the compiler thinks will be most efficient, or on  
what a calling convention requires.

Since the content is not writable (except by using ugly tricks, in  
which case the programmer himself is responsible for messing up  
things), that does not matter.

> - 'out': I'm not sure if it's more similar to 'var' or ''.

It's like var, except that in some cases the contents of the "out"  
parameter are erased before the function call, and that you get  
different warnings regarding the initialised status of an out  
parameter and the values that you pass to them.


Jonas_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

L505
In reply to this post by Michael Müller-4

> > Only the pointer itself is the parameter and read-only. Where the pointer
> > points to is irrelevant.

I remember this from using classes where you can still access the class properties -
should have thought about that before posing the question :).

>
> But in this case I'm wondering why you want to give a pointer instead
> of the real type?


did you mean this ? :

   procedure ChangeRec1(const Rec: TSomeRec);
   begin
     Rec.a:= 'string A';
   end;

Because I can't pass a PSomeRec to that function, only a TSomeRec

Otherwise, I don't know what you mean..

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Jonas Maebe-2

On 01 May 2006, at 20:07, L505 wrote:

> did you mean this ? :
>
>    procedure ChangeRec1(const Rec: TSomeRec);
>    begin
>      Rec.a:= 'string A';
>    end;
>
> Because I can't pass a PSomeRec to that function, only a TSomeRec

Then pass a PSomeRec^ to it if you don't intend to change the pointer  
anyway.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

L505


>
> > did you mean this ? :
> >
> >    procedure ChangeRec1(const Rec: TSomeRec);
> >    begin
> >      Rec.a:= 'string A';
> >    end;
> >
> > Because I can't pass a PSomeRec to that function, only a TSomeRec
>
> Then pass a PSomeRec^ to it if you don't intend to change the pointer  
> anyway.
>

That works, I was getting sloppy with Delphi style code who doesn't always require the ^
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

Michael Müller-4
In reply to this post by L505
On Mon, May 01, 2006 at 12:07:55PM -0600, L505 <[hidden email]> wrote:

>
> > > Only the pointer itself is the parameter and read-only. Where the pointer
> > > points to is irrelevant.
>
> I remember this from using classes where you can still access the class properties -
> should have thought about that before posing the question :).
>
> >
> > But in this case I'm wondering why you want to give a pointer instead
> > of the real type?
>
>
> did you mean this ? :
>
>    procedure ChangeRec1(const Rec: TSomeRec);
>    begin
>      Rec.a:= 'string A';
>    end;

Yes.

> Because I can't pass a PSomeRec to that function, only a TSomeRec

Where is the problem? If you allocated the memory by new() as in your
example you could call
ChangeRec1(RecPtr^);
and the compile (hopefully) uses the pointer.

But in this case you will get an compiler error because you can't
change a constant value.

It seemed that I didn't get the point from your original mail:
Name the procedure CHANGERec1 and change a value but declare the
parameter as constant.

> Otherwise, I don't know what you mean..

Now _I_'m a little bit confused.

Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: const parameter writeable

L505
> > >
> > > But in this case I'm wondering why you want to give a pointer instead
> > > of the real type?
> >
> >
> > did you mean this ? :
> >
> >    procedure ChangeRec1(const Rec: TSomeRec);
> >    begin
> >      Rec.a:= 'string A';
> >    end;
>
> Yes.

Well, this is a Precord. That doesn't work. That is why I was confused.

>
> > Because I can't pass a PSomeRec to that function, only a TSomeRec
>
> Where is the problem? If you allocated the memory by new() as in your
> example you could call
> ChangeRec1(RecPtr^);
> and the compile (hopefully) uses the pointer.

Yes, but you are repeating what Jonas says - if you would have told me this first, you
would have gotten the brownie points. But Jonas gets them. :-)

>
> But in this case you will get an compiler error because you can't
> change a constant value.
>
> It seemed that I didn't get the point from your original mail:
> Name the procedure CHANGERec1 and change a value but declare the
> parameter as constant.

I was asking why I could write to a const. But in fact I was not writing to the CONST, I
was actually writing to the const data it pointed to.  With SomeRec^ I cannot write to
const. Problem solved.

I was using sloppy Delphi style code without ^ since Delphi enforces this sloppy style of
coding, and now I know why not to use sloppy delphi style code.

What I was confused about was why you recommended TSomeRec when we are dealing with
PSomeRec.

I also stated that I knew you can pass TSomeClass as a const, you can still access it's
properties even though it is a const.

 program project1;

 {$mode objfpc}{$H+}

   type
     TSomeClass = class
       a: string;
       b: string;
     end;

   procedure ChangeClass(const SomeClass: TSomeClass);
   begin
     SomeClass.a:= 'string A';
   end;

 var
   SomeClass: TSomeClass;
 begin
   someclass:= TSomeClass.create;
   ChangeClass(someclass);
   writeln(someclass.a);
   someclass.free;
   readln;
 end.

This is normal, because we are passing a pointer when dealing with a class - not passing
the class contents. Which is really what I should have thought about before asking the
question, because I have discovered you can write to a const class *contents* before.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal