strlen_P versus sizeof

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wonder about you ideas of using sizeof for string lenghts in flash. It seems to work all right.

My guess is this could only go wrong if the string itself contains zero's, but then it wouldn't be a proper string in the first place.

It also would not work if the strings in flash are updated with self programmin mode, but that's not a normal operation.

Did I forget something here or could this be a good optimisation?

#include 
PROGMEM char Text_P[] = "Hello World.";

void main(void)
{
    int x,y;

    x = strlen_P( Text_P);    // Function call.
    y = sizeof( Text_P) - 1;  // Constant, subtract final zero.
}

//========================================================================

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure I understand why they'd even have bothered with supplying strlen_P() though I suppose you may only be passing around a pointer to the string in which case you'd need the function to get the length. But as long as the pointed data itself is visible I'd always use the compile time sizeof() for the advantages you suggest.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That depends on how the strings are declared. It's not uncommon to use a fixed size for flash strings regardless of actual string length.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
My guess is this could only go wrong if the string itself contains zero's, but then it wouldn't be a proper string in the first place.
But surely it is possible and perfectly legal to produce an array of chars that is not a "proper string".

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Conclusion: It's a good idea to do it this way but it has it's limitations
(Just as about anything in life).

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't get it.

On the one hand, just slightly change the code and you'll get garbage:

#include 

PROGMEM const char Text_P[] = "Hello World.";

size_t y;

size_t f (const char *str)
{
    return sizeof (str) - 1;
}

void main (void)
{
    y = f (Text_P) - 1;
}

Will set y to 1.

On the other hand, strlen_P is smart enough to compute the length at compile time if it is known at compile time.

Thus, your approach gains nothing and is error prone.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
On the other hand, strlen_P is smart enough to compute the length at compile time if it is known at compile time.
... since 2011 (i.e. not in WinAVR20100110).

https://savannah.nongnu.org/bugs...

(The story is, that reading this thread I faintly recalled having read about strlen_P() optimizing for known-at-compile-time; the result of googling truly surprised me... :-( ).

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
On the other hand, strlen_P is smart enough to compute the length at compile time if it is known at compile time.

Thus, your approach gains nothing and is error prone.

I'm pretty sure the smarts are in the compiler.
Is there documentation to the effect that the compiler will do the computation?
So far as I can tell, the only hint that the compiler is even allowed to do that is the angle brackets.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just read strlen_P.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course it's the compiler which does the heavy lifting through builtin functions - see the strlen_P definition in your copy of and the link given at the link I gave above (speaking of pointers).

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
Of course it's the compiler which does the heavy lifting through builtin functions - see the strlen_P definition in your copy of and the link given at the link I gave above (speaking of pointers).
Apparently some regard bugzilla as standard documentation.
'Tain't anywhere I would have found it without help.
I'm sure people unfamiliar with GNU builtins would find it interesting.
My copy of pgmspace.h seems to be from 2010.
It doesn't say much of anything about what strlen_P does.
The only relevant comment is "/* program memory can't change */".
Are more recent versions better commented?

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Are more recent versions better commented?

Well I was going to suggest that the online copy of the AVR-LibC documentation (which is basically Doxygen'd from the .h files themselves) always reflects the latest release so look at:

http://nongnu.org/avr-libc/user-...

However that does not admit to the existence of a strlen_P() function any more. Only strlen_PF(). So has strlen_P() and the other _P functions been deprecated/withdrawn? That seems a bit harsh, there must be tons of legacy code using them.

EDIT: looking at the HEAD of SVN shows:

http://svn.savannah.nongnu.org/v...

So the functions are still there even if the manual no longer mentions them. The curious thing though is that the pgmspace.h at HEAD doesn't seem to have the Doxygen that generated the documentation for the _PF functions either.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you reading doxygen? It's just some arbitrary text.

Read the C part. That is the read thing.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
Why are you reading doxygen? It's just some arbitrary text.

Read the C part. That is the read thing.

We will never agree on this.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Well I was going to suggest that the online copy of the AVR-LibC documentation (which is basically Doxygen'd from the .h files themselves)

Point is, that it's not only the .h files, but also the C/asm sources, which contain the documentation. The common user does not have the latter sources.

The comment has been properly updated thanks to Eric, when he applied the "patch":

strlen_P.S wrote:
\note strlen_P() is implemented as an inline function in the avr/pgmspace.h
header file, which will check if the length of the string is a constant
and known at compile time. If it is not known at compile time, the macro
will issue a call to __strlen_P() which will then calculate the length
of the string as normal.
but for some reason to me unknown (I don't doxygen and I don't build and publish) it did not appear where it was supposed to, which is http://www.nongnu.org/avr-libc/u... . In my off-line copy of group__avr__pgmspace.html coming from the 2007-vintage WinAVR I use the comment is there (in its older form of course), so something has broken in between.

That it is not a good idea to have two files documenting the same thing, is for another discussion.

JW