Is there a "bitness dependent" boolean type in FPC ? lazarus / 62-General ---------------------------------------------------------------------- 440bx · 2020-02-19 18:06 Hello, ptrint and ptruint change size depending on the target bitness and, that is often convenient. I was wondering if there was a Boolean (ptrboolean ?) type that would also change in size depending on the target bitness and, that is my question, is there such a Boolean type in FPC ? Thank you for your help. ---------------------------------------------------------------------- marcov · 2020-02-19 18:12 Boolean or Bool? But since the boolean is not a variable type like pointer is, and always one byte, in practice it probably doesn't matter, contrary to languages that map boolean onto integer types. ---------------------------------------------------------------------- Remy Lebeau · 2020-02-19 18:17 Quote from: 440bx on February 19, 2020, 07:06:31 pmptrint and ptruint change size depending on the target bitness and, that is often convenient. The bitness size you refer to only applies to pointers.  PtrInt and PtrUInt exist to store pointers in integer types, so of course they have to adjust size to accommodate the correct size of a pointer.  But that makes no sense to do for a boolean. Quote from: 440bx on February 19, 2020, 07:06:31 pmI was wondering if there was a Boolean (ptrboolean ?) type that would also change in size depending on the target bitness No.  Why do you need this?  A boolean is just a true/false value, so only 1 byte is needed for it. If you really need a multi-byte boolean, there are several existing types available: 2 bytes: WordBool and Boolean164 bytes: LongBool and Boolean328 bytes: QWordBool and Boolean64 But there is no existing type to match the bitness size of a pointer.  You will just have to create your own alias for that, eg: Code: [Select]{$IFDEF CPU32} type   PtrBoolean = Boolean32; // or LongBool {$ENDIF} {$IFDEF CPU64} type   PtrBoolean = Boolean64; // or QWordBool {$ENDIF} ---------------------------------------------------------------------- 440bx · 2020-02-19 18:58 Quote from: marcov on February 19, 2020, 07:12:00 pmBoolean or Bool? As long as it changes size with the bitness, either would do.   Spandex Boolean Quote from: marcov on February 19, 2020, 07:12:00 pm contrary to languages that map boolean onto integer types. that's exactly what I need at this time.  A pointer that can be interpreted as false if nil and true if not. Thank you Marco. Quote from: Remy Lebeau on February 19, 2020, 07:17:04 pmThe bitness size you refer to only applies to pointers.  PtrInt and PtrUInt exist to store pointers in integer types, so of course they have to adjust size to accommodate the correct size of a pointer.  But that makes no sense to do for a boolean. It is quite convenient when the majority of the time, all that matters is knowing if the pointer is not nil and, dereferencing the pointer is needed only a few times.  In that case, defining a function's return value as "booleanptr" would be convenient. Quote from: Remy Lebeau on February 19, 2020, 07:17:04 pmNo.  Why do you need this?  A boolean is just a true/false value, so only 1 byte is needed for it. Because there is a function that most of the time, I only need to know if it found what I told it to search for (true/false) but, there are a very few times when it is necessary to inspect what it found.  Being able to interpret its Boolean return as a pointer to a structure to inspect its content would be quite convenient. Quote from: Remy Lebeau on February 19, 2020, 07:17:04 pmIf you really need a multi-byte boolean, there are several existing types available: 2 bytes: WordBool and Boolean164 bytes: LongBool and Boolean328 bytes: QWordBool and Boolean64Yes, but I need a Boolean type that changes with the bitness because it is actually a pointer. Quote from: Remy Lebeau on February 19, 2020, 07:17:04 pmBut there is no existing type to match the bitness size of a pointer.  You will just have to create your own alias for that, eg: Code: [Select]{$IFDEF CPU32} type   PtrBoolean = Boolean32; // or LongBool {$ENDIF} {$IFDEF CPU64} type   PtrBoolean = Boolean64; // or QWordBool {$ENDIF} That's what I did.  Thank you Remy. ---------------------------------------------------------------------- Remy Lebeau · 2020-02-19 19:13 Quote from: 440bx on February 19, 2020, 07:58:18 pmthat's exactly what I need at this time.  A pointer that can be interpreted as false if nil and true if not. That is not how things work.  And you seem to have a fundamental misunderstanding of what bools and pointers actually are and how they work. If you need to know if a pointer is nil, just compare it directly: Code: [Select]if pointer = nil then Code: [Select]if pointer <> nil then The '=' and '<>' operators return an actual Boolean, no conversion needed. Quote from: 440bx on February 19, 2020, 07:58:18 pmIt is quite convenient when the majority of the time, all that matters is knowing if the pointer is not nil and, dereferencing the pointer is needed only a few times.  In that case, defining a function's return value as "booleanptr" would be convenient. That makes no sense whatsoever.  A Pointer-to-boolean is not the same thing as a Pointer-sized-boolean.  Two completely different things. Quote from: 440bx on February 19, 2020, 07:58:18 pmBecause there is a function that most of the time, I only need to know if it found what I told it to search for (true/false) but, there are a very few times when it is necessary to inspect what it found.  Being able to interpret its Boolean return as a pointer to a structure to inspect its content would be quite convenient. You are confused.  What you NEED to do is return an ACTUAL POINTER to the data that was found.  If nothing was found, return a nil pointer.  The CALLER can then check if the pointer is nil or not, and if not then dereference it if needed.  Converting the pointer to a boolean is NOT what you want, especialy for those few times where you WANT to inspect the data.  Converting the pointer, you lose access to the data. And besides, you DO NOT need to convert the pointer to a pointer-sized boolean in this situation anyway.  Just because you need to work with a pointer to data does not mean you have to work with a pointer-sized boolean, too. Code: [Select]function Find(params): Pointer; begin   ...   if (found) then     Result := pointer to data   else     Result := nil; end; ... if Find(params) <> nil then begin   // found, do something... end else begin   // not found, do something else... end; ... var   data: Pointer; data := Find(params); if data <> nil then begin   // found, use data as needed... end else begin   // not found, do something else... end; Alternatively, if you really don't need the data pointer most of the time, just do this instead: Code: [Select]function Find(params; var Data: Pointer): Boolean; overload; begin   ...   if (found) then begin     Data := pointer to data;     Result := True;   end else     Result := False; end; function Find(params): Boolean; overload; var   Ignore: Pointer; begin   Result := Find(params, Ignore); end; ... if Find(params) then begin   // found, do something... end else begin   // not found, do something else... end; ... var   data: Pointer; if Find(params, data) then begin   // found, use data as needed... end else begin   // not found, do something else... end; You are making things more complicated than they need to be. Quote from: 440bx on February 19, 2020, 07:58:18 pmYes, but I need a Boolean type that changes with the bitness because it is actually a pointer. No, you really don't. ---------------------------------------------------------------------- 440bx · 2020-02-19 21:44 Quote from: Remy Lebeau on February 19, 2020, 08:13:04 pmIf you need to know if a pointer is nil, just compare it directly: That's what I don't want to have to do.   The great majority of the time, all I need is to know if the entry in the table was found, I don't need to inspect the entry. I'm used to the way it's done in C.  That's what I'd like to have, just test without having to type "= nil" or "<> nil" all the time,  just because, on rare occasions I need to use the pointer. Quote from: Remy Lebeau on February 19, 2020, 08:13:04 pmNo, you really don't. Yes, I do. The workaround you suggested works.  I defined a TNATIVE_BOOLEAN that changes size with the bitness and I "absolute" a pointer on top of that when I need to inspect the entry.  It's pedestrian and not elegant but, it gets the job done. ---------------------------------------------------------------------- jamie · 2020-02-19 22:09 You are looking for something that will never happen in FPC, because I've asked for a few times and all I get is flack about it.. All types without any Boolean expressions or otherwise should default to a Boolean expression if these are types, not functions etc..  In your case.. If SomePointer then …. or  If Not SomePointer then.... Basically, being any form of a number type or pointer can be tested for a 0 value to indicate if it's tree of false, false for 0 / Nil otherwise true for all other values  I don't know if there are helpers for pointers, maybe there should be if not but with other numerical types you do have this..  If SomeInteger.ToBoolean then.... So my question here is , why can't we do this..  If SomeInteger then.....  Oh well, I understand the frustration that comes with it.  you can do this however,. If Boolean(SomePotiner) then the compiler may decide to only examine the low byte and so on.. But I think making a pointer helper adding to one for a bool is a good idea and the helper should also be able to auto detect a Boolean operation if there is nothing defind.. for example  if SomePointer then..  In the helper there would be a default call of returning a Boolean results or inline generated code. The proper way to do this is at the compiler intrinsic level where the compiler can property code it without the over head..  Maybe if we ask enough we could get it ---------------------------------------------------------------------- marcov · 2020-02-19 22:16 Quote from: 440bx on February 19, 2020, 10:44:44 pmQuote from: Remy Lebeau on February 19, 2020, 08:13:04 pmIf you need to know if a pointer is nil, just compare it directly: That's what I don't want to have to do.   The great majority of the time, all I need is to know if the entry in the table was found, I don't need to inspect the entry. I'm used to the way it's done in C.  That's what I'd like to have, just test without having to type "= nil" or "<> nil" all the time,  just because, on rare occasions I need to use the pointer. Be very careful then. For Boolean types, all values except 0 and 1 are undefined, so they might return false even when not 0.  It might be translated to "test  eax,1" or so, so all even values would be false, and all odd values would be true. Assuming other languages constructs port over to the same semantics is not a wise thing to do. The boolean<-> integer <-> pointer equivalence is much weaker in Pascal than in C. ---------------------------------------------------------------------- Remy Lebeau · 2020-02-19 22:35 Quote from: 440bx on February 19, 2020, 10:44:44 pmThe great majority of the time, all I need is to know if the entry in the table was found, I don't need to inspect the entry. Then you should write your search function to return a standard Boolean.  You don't need a pointer-sized Boolean, that is just a waste of memory. Quote from: 440bx on February 19, 2020, 10:44:44 pmI'm used to the way it's done in C.  That's what I'd like to have, just test without having to type "= nil" or "<> nil" all the time C does an implicit conversion from a pointer to a bool for you in contexts where a bool is expected, like in an 'if' statement.  Pascal simply does not work that way, pointer comparisons must be done explicitly. Quote from: 440bx on February 19, 2020, 10:44:44 pmjust because, on rare occasions I need to use the pointer. Then you should just return a pointer and compare it explicitly.  Without using some kind of separation of bool and data, like I showed you in my previous reply, another option is something like this, which is just nuts: Code: [Select]{$IFDEF CPU32} type   BooleanPtr = LongBool; {$ENDIF} {$IFDEF CPU64} type   BooleanPtr = QWordBool; {$ENDIF} function Find(params): Pointer; begin   ...   if (found) then     Result := pointer to data   else     Result := nil; end; ... //if Find(params) <> nil then if BooleanPtr(Find(params)) then begin   // found, do something... end else begin   // not found, do something else... end; ... var   data: Pointer; data := Find(params); //if data <> nil then if BooleanPtr(data) then begin   // found, use data as needed... end else begin   // not found, do something else... end; Quote from: 440bx on February 19, 2020, 10:44:44 pmQuote from: Remy Lebeau on February 19, 2020, 08:13:04 pmNo, you really don't. Yes, I do. No, you really don't.  You are just being lazy, making your code require more typing and be uglier and harder to maintain. ---------------------------------------------------------------------- Remy Lebeau · 2020-02-19 22:38 Quote from: jamie on February 19, 2020, 11:09:41 pm you can do this however,. If Boolean(SomePotiner) then the compiler may decide to only examine the low byte and so on.. Which won't work for non-nil pointers whose low byte happens to be 0. ---------------------------------------------------------------------- winni · 2020-02-19 22:52 Hi! Make it save and crazy: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if boolean (odd(Qword(MyPointer))) then Winni ---------------------------------------------------------------------- 440bx · 2020-02-19 23:52 Quote from: marcov on February 19, 2020, 11:16:01 pm It might be translated to "test  eax,1" or so, so all even values would be false, and all odd values would be true. I checked that, it does a "test reg, reg" Quote from: marcov on February 19, 2020, 11:16:01 pmAssuming other languages constructs port over to the same semantics is not a wise thing to do. I couldn't agree anymore, which is why I asked if some type worked just as BOOL does in C. Quote from: Remy Lebeau on February 19, 2020, 11:35:17 pmYou are just being lazy, making your code require more typing and be uglier and harder to maintain. I'm not being lazy.  It doesn't make much sense to me to change about a hundred calls because less than 5 of them require the pointer.  It's the tail wagging the dog. This case has no solution I like.  It's this kind of stuff that reminds me why I still use C in spite of the fact that I strongly dislike it. ---------------------------------------------------------------------- jamie · 2020-02-20 02:38 I feel your pain, really   The compiler should at least allow a helper to have a default sub member call to allow us short hand coders to implement such behavior. Or just put in there !   I can picture the key word "DEFAULT" being used in a type helper to  have it excute a ToBoolean expression. Or just simply inline the equation..  If SomePointer then..  would end up being  If SomePointer <> Nil then...  Or  If SomePointer.ToBoolean then..  but in the Type define record for the ToBoolean section, just put a DEFAULT at the end. of course the compiler needs to be updated to do this.. I've already tried this and it does not work  The same goes for other types like Managed types.. If SomeString then.... would generate code like If SomeString <> '' Then …. etc.. But this should only work when ever Boolean expressions are applicable. I don't really see the issue here because if you use a function with a Boolean results you don't need to do this If SomeFunction = True then... So where we are in the modern days of coding and this is what we live with.. I like C for somethings but object syntax still beats it, it would be a lot nicer of we could just merge some more good ideas from C into this . ---------------------------------------------------------------------- Thaddy · 2020-02-20 08:00 Since 3.0 true and false are not keywords anymore, so you can do things like this (on a per unit basis or qualified with a unit prefix: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode delphi}{$H+}const  false = nil;  true = not PtrUint(false); // needs a cast, of course // you can also make sure like : Pointer(not PtrUint(false))beginend.If this is useful? dunno, but it works... Now true and false are pointer types..... (Rather proud of this......silly solution...) https://wiki.freepascal.org/User_Changes_3.0#True_and_False_are_not_ke ywords_anymore [edit] To my surprise this actually works! ---------------------------------------------------------------------- PascalDragon · 2020-02-20 09:08 Quote from: 440bx on February 20, 2020, 12:52:40 amQuote from: marcov on February 19, 2020, 11:16:01 pmAssuming other languages constructs port over to the same semantics is not a wise thing to do. I couldn't agree anymore, which is why I asked if some type worked just as BOOL does in C. Be sure to use LongBool and QWordBool then. Using Boolean32 and Boolean64 would lead to trouble in your context sooner or later. Quote from: 440bx on February 20, 2020, 12:52:40 amQuote from: Remy Lebeau on February 19, 2020, 11:35:17 pmYou are just being lazy, making your code require more typing and be uglier and harder to maintain. I'm not being lazy.  It doesn't make much sense to me to change about a hundred calls because less than 5 of them require the pointer.  It's the tail wagging the dog. This case has no solution I like.  It's this kind of stuff that reminds me why I still use C in spite of the fact that I strongly dislike it. Declaring your own alias is the solution. PtrInt and PtrUInt are declared like that as well, so there is nothing inherently wrong with that. ---------------------------------------------------------------------- Thaddy · 2020-02-20 09:48 So my example is not so weird after all? I still think it is wacky... ---------------------------------------------------------------------- 440bx · 2020-02-20 10:03 Quote from: Thaddy on February 20, 2020, 09:00:47 amSince 3.0 true and false are not keywords anymore Looks like the reason was Delphi compatibility.  I don't care much for that kind of "flexibility".  It opens the open the door to all kinds of rather surprising situations because someone decided to flip the meaning of true and false.   Got to love it.  Other than having a potential to create headaches, it seems to be totally useless. Quote from: PascalDragon on February 20, 2020, 10:08:28 amBe sure to use LongBool and QWordBool then. Using Boolean32 and Boolean64 would lead to trouble in your context sooner or later. Declaring your own alias is the solution. PtrInt and PtrUInt are declared like that as well, so there is nothing inherently wrong with that. Ultimately, I wasn't satisfied with any of the options. I figured another way of getting the stuff done without having to inspect the contents the data structure, that way the function can return a real Boolean. However, thank you for the good advice, I appreciate it. ---------------------------------------------------------------------- Thaddy · 2020-02-20 10:29 Quote from: 440bx on February 20, 2020, 11:03:07 amit seems to be totally useless. Except in your case? ---------------------------------------------------------------------- 440bx · 2020-02-20 10:36 Quote from: Thaddy on February 20, 2020, 11:29:53 amQuote from: 440bx on February 20, 2020, 11:03:07 amit seems to be totally useless. Except in your case? When I find myself doing stuff like that, that's when I know I have to rethink the method.  It's useful for that. ---------------------------------------------------------------------- Thaddy · 2020-02-20 10:54 Quote from: 440bx on February 20, 2020, 11:36:08 amWhen I find myself doing stuff like that, that's when I know I have to rethink the method.  It's useful for that. That's called C programming.... Anyway, what you asked is possible within the confines of the language.  Recommended? of course not! But then again, you yourself referred to C style languages, so why not accept the solutions while you embrace the C solution? Which is by accident and not by design... An oversight that became a feature. C is a rather incomplete language, I dare say frivolous, even gratuit, There is something wrong with your reasoning....