So if possible do not use a typed const, but a literal string, untyped const. x86_64 or i386 code will look very similar:with the pre-calculated length.Thanks Thaddy. If the constant is not typed then simply sizeof(thecharacterconstant) returns the number of characters in the constant which is nice but, unfortunately doing it way that leads to some undesirable problems when using arrays.
In the case of typed consts, length() will actually execute code for string length(examine size field) or code for PChar len, which actually calls strlen anyway.
Better simply use length(), that works also on PChars. The compiler generates about the same code as strlen.The compiler knows the length of the string but, it refuses to give it up at compile time. It has no problem handing it over at run time. I tried assigning s[0] to a constant. It didn't like it. Also tried length and a number of other "creative" ways of extracting the length at compile time, all to no avail.
TC_$P$UNTITLED_$$_SOMECHARACTERS: .byte 22 ; <--- shortstring length
type Tarray = array[0..1] of pchar; const // sizeof returns the size of these constants charconst1 = 'character constant 1'; charconst2 = 'character constant 2 - made purposely larger'; // this variable declaration gives the compiler quite a headache. :-) var carray : tarray absolute charconst1;
No, just no. Such a declaration is an absolute accident waiting to happen as the compiler is free to place the two constant where it wants and if it thinks that a third, completely unrelated constant fits nicely between charconst1 and charconst2 than it will do so, thus breaking your array.What I want couldn't be any simpler, I want to have the count of characters in a constant array of characters _at compile time_ (the compiler has that information but, it won't give it up). Nothing particularly extravagant, parallel to sizeof(sometype) but for constant arrays. Having those constants would be helpful, just as having high/low of an array allows other arrays/data types to be "customized" to fit them. Nothing "strange" in that.
Maybe it's best for you to explain what you want to achieve in the end instead of posting strange abuses of array, absolute and PChar. This way we could try to find a solution that's efficient, but also maintainable.
I think the gain is not worth the trouble, since both untyped literals as shortstring literals are assignment compatible to the other string types, even Pchar.You're definitely right about that. I asked the question to make sure there wasn't some feature in FPC, that I was not aware of, that would yield those values. I'll just determine the length at runtime. As you pointed out, it really won't take much code to get the lengths and use them.
The compiler knows at compile time how many characters are pointed to by the constant pointer "somecharacters" and, that's what I'd like to get.
const somecharacters : pchar = 'an array of characters';
Even so: project1.lpr(10,5) Warning: unreachable codeThe compiler obviously knows the length of the character array constant. There just doesn't seem to be any way of getting it at compile time. That's unfortunate, there are times when that information is useful.
There is only one copy of a line in the executable.
How about letting the IDE deal with counting array elements instead of the compiler doing it?That is a nice idea but, it has one major downside. If a string is changed (made smaller or longer) and the programmer forgets to tell the IDE to "update" the dependent locations then, things are no longer in sync. Additionally, it's difficult to trust the IDE to do those things correctly since the IDE usually, unlike the compiler, has a limited view of the entire program.
Something like https://forum.lazarus.freepascal.org/index.php?topic=27186.15
If you do a shortstring (max len 255) and sizeof(), maybe that will do. (not tested, and if it works may be one extra)Unfortunately, even with a shortstring, the compiler does not allow using the length of the string at compile time. For instance, it will not accept "const Mylength = mystring[0];" or "const mylength = length(mystring);". Taking sizeof(shortstring) will yield a value that is the size of a shortstring, not the size/character count of the string it holds (which is reasonable since, as you know, that is not a constant, it's just an initialized variable.)
const foo = shortstring('abc');
With ansistring that will not work, since sizeof(ansistring) = sizeof(pointer).
What would you do want to do with the value, if you could get it?
Which is interesting, because a shortstring also contains the length of the string, so I expected 10.As I am sure you know, the typecast doesn't convert the string into a shortstring. It is still a null terminated array of characters. If it had done a conversion, the sizeof it would have been 256.
Without a typed const, indeed... the compiler simply translates it into a string literal if you use an untyped const declaration, with or without type indication by cast.This is a port of a C program to FPC. I could take all the C null terminated character arrays and convert them into Pascal strings. That's always an option but, it makes the port more complicated because some of the strings are longer than 255 characters. I could use AnsiStrings which can host more than 255 characters, if I go that route I open the door to potential problems since they are a managed type (reference counted.)
But is the strlen not really your issue? and that is really not necessary unless interfacing with C (and the likes) code.
In mode $H+ pascal strings are practically unlimited in length.
On a 32 bit platform. Yes. And even that depends. :)In mode $H+ pascal strings are practically unlimited in length.
@Thaddy, I guess you wanted to say limited to 2GB right? :)
program Project1; const foo = shortstring('abc123def'); l = sizeof(foo); begin writeln(l); readln; end.
Compiles and prints 9. (that is bytes, not chars, in case of utf8)
Which is interesting, because a shortstring also contains the length of the string, so I expected 10.
Delphi (7) prints 256 (which is what I expected, since shortstring is string[255] and it occupies 256 bytes of memory).
No idea about more modern Delphi's.
Bart
Bart, Delphi and FPC reserve 256 bytes, but store the shortstring correct, with size. Hence length.
program Project1; const foo = shortstring('abc123def'); l = sizeof(foo); begin writeln(l); readln; end.
Compiles and prints 9. (that is bytes, not chars, in case of utf8)
Which is interesting, because a shortstring also contains the length of the string, so I expected 10.
Delphi (7) prints 256 (which is what I expected, since shortstring is string[255] and it occupies 256 bytes of memory).
No idea about more modern Delphi's.
Bart
Bart, Delphi and FPC reserve 256 bytes, but store the shortstring correct, with size. Hence length.FPC doesn't reserve 256 bytes. It reserves 0 bytes. Unlike in Delphi, after compiling, there is no trace of foo in the executable (except if debug info is requested, then its existence as a constant appears in the debugging information.)
Uhhhhh. Wrong again.Bart, Delphi and FPC reserve 256 bytes, but store the shortstring correct, with size. Hence length.FPC doesn't reserve 256 bytes. It reserves 0 bytes. Unlike in Delphi, after compiling, there is no trace of foo in the executable (except if debug info is requested, then its existence as a constant appears in the debugging information.)
Count them... that is 255 + the .byte 22.....I have no doubt you see them, that along with a few pink elephants and a few cases of bottles of wine, which is the probably the one thing you are good at, drinking it.
I didn't say it's perfect. I just don't think you have a better solution at this moment. If it was for me I would make IDE script even more simple - just count commas in a selection and add 1 to the result and put it where it belongs in the code. Crude but should do the work.How about letting the IDE deal with counting array elements instead of the compiler doing it?That is a nice idea but, it has one major downside. If a string is changed (made smaller or longer) and the programmer forgets to tell the IDE to "update" the dependent locations then, things are no longer in sync. Additionally, it's difficult to trust the IDE to do those things correctly since the IDE usually, unlike the compiler, has a limited view of the entire program.
Something like https://forum.lazarus.freepascal.org/index.php?topic=27186.15
I didn't say it's perfect. I just don't think you have a better solution at this moment. If it was for me I would make IDE script even more simple - just count commas in a selection and add 1 to the result and put it where it belongs in the code. Crude but should do the work.Don't get me wrong. I appreciate the suggestion. The goal of the question is/was to find out if there was a reliable mechanism of determining the lengths at compile time so they could be used to define buffers of the right sizes, that would be automatically updated by the compiler if any changed.
If You are looking for something else then it eludes me..
I just created 3 non-writable constants containing the text then finalized it with a writable constant of the whole thatyes, that is no problem. The problem is that the SomeMaxSize you declare is not based on the sizes of the three constants. Someone can change the constants in such a way that they exceed SomeMaxSize then there is a problem. If SomeMaxSize could be determined based on the sizes of the constants then the code would always work before the buffer size, calculated by the compiler, is always large enough.
works compile time and also allows for a max size...
Const SomeText = ' Some text'; MoreText = 'MoreText'; AlittleMore = ' AlittleMore'; TotalBuffer = Array[0..SomeMaxSize] of char = SomeText+MoreText+AlittleMore;
So what ever you want with it at runtime afterwards.
TotalBuffer that is..
Only 1 minor detail: The length of the string must be > 1. If I remove the space in front of the ' !', it gives a type mismatch (expected 'char').
Done: 0039030
My first one, so hope it's clear