Length prefixed strings in C In want to implement length prefixed strings in C (not null terminated), with some idiosyncrasies: malloc is prohibited, memory efficiency is important, each string (except for literal-backed ones) is modifiable and can change its length, but it has a fixed (at declaration) allocated length (maximum 255), C code is generated by a code generator.  I want this to work on as many architectures and C compilers as possible.

Suppose I do the following:

typedef struct PLS { 
   uint8_t maxlen; 
   uint8_t curlen; 
   char buf[1];  // actual allocated size is in maxlen 
} PLS ; 


Then I could declare, say

  struct {
    ...
    PLS s1;   // real allocated size: 100
    char s1buf[99];
    PLS s2;  // real allocated size: 64 
    char s2buf[63];
    ...
    };

   // initialization:
   mystruct.s1.maxlen=100;
   mystruct.s1.curlen=0;
   mystruct.s2.maxlen=64;
   mystruct.s2.curlen=0;

   // PLS library:

   void PLS_copy(PLS *to,PLS *from) {
       int tc = from-&gt; curlen; // chars to copy
       if(tc &gt; to-&gt;maxlen) tc = to-&gt;maxlen;
       memcpy(to-&gt;buf,from-&gt;buf,tc);
   }


Does this look ok? Any pitfalls? Would some compiler give warnings?
I believe that data structure alignment should not padding between s1 and s1buf, but even then it should work, right?

For literals, if I want to avoid a duplication of allocated chars, things seem trickier (remember, though, that code is machine-generated). Would this be objectionable?

 // static declaration of literal "hello" (5 chars) trailing null byte wasted
 char lit1[] = "\x05\x05hello"; 
// can the above be casted to PLS? (I won't modif it, I swear)
 PLS * lit1Pls = &amp;(PLS)(lit1);  // smells funny, though...
Copy function improvements

Your copy function could be better:


   void PLS_copy(PLS *to,PLS *from) {
       int tc = from-&gt; curlen; // chars to copy
       if(tc &gt; to-&gt;maxlen) tc = to-&gt;maxlen;
       memcpy(to-&gt;buf,from-&gt;buf,tc);
   }




You could use const on your from argument.
You never update the length of the to string.  I'm assuming this is like a strcpy, so the to string should have its length set to the length that you just copied.


Here is how I would write it:

   void PLS_copy(PLS *to, const PLS *from)
   {
       uint8_t bytesToCopy = from-&gt;curlen;

       if (bytesToCopy &gt; to-&gt;maxlen)
           bytesToCopy = to-&gt;maxlen;
       memcpy(to-&gt;buf, from-&gt;buf, bytesToCopy);
       to-&gt;curlen = bytesToCopy;
   }


Flexible array member

I agree with the comment by M.M about using flexible array members instead of buf[1]:

typedef struct PLS { 
   uint8_t maxlen; 
   uint8_t curlen; 
   char buf[];  // actual allocated size is in maxlen 
} PLS;

struct {
    ...
    PLS s1;   // real allocated size: 100
    char s1buf[100];
    PLS s2;  // real allocated size: 64 
    char s2buf[64];
    ...
};


Also, you could use a macro to help declare these fields.  Something like this:

#define PLS_FIELD(name, length)  \
    PLS name;                    \
    char name##buf[length]


Then you could define your struct as:

struct {
    ...
    PLS_FIELD(s1, 100);
    PLS_FIELD(s2, 64);
    ...
};


Casting literal

For your literal casting, I would do this:

char lit1[] = "\x05\x05hello";
const PLS *lit1Pls = (const PLS *) lit1;


The const keyword here will prevent you from writing to the literal.  And the cast I used is simpler than the one you used.  I don't see anything objectionable about doing this.