In C, is there a good way to define length first, Pascal-style strings as constants, so they can be placed in ROM? (I\'m working with a small embedded system with a non-GCC
This is why Variable Length Arrays were introduced in c99 (and to avoid the use of the "struct hack") IIRC, Pascal-strings were limited to a maximal length of 255.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> // For CHAR_BIT
struct pstring {
unsigned char len;
char dat[];
};
struct pstring *pstring_new(char *src, size_t len)
{
struct pstring *this;
if (!len) len = strlen(src);
/* if the size does not fit in the ->len field: just truncate ... */
if (len >=(1u << (CHAR_BIT * sizeof this->len))) len = (1u << (CHAR_BIT * sizeof this->len))-1;
this = malloc(sizeof *this + len);
if (!this) return NULL;
this->len = len;
memcpy (this->dat, src, len);
return this;
}
int main(void)
{
struct pstring *pp;
pp = pstring_new("Hello, world!", 0);
printf("%p:[%u], %*.*s\n", (void*) pp
, (unsigned int) pp->len
, (unsigned int) pp->len
, (unsigned int) pp->len
, pp->dat
);
return 0;
}
You can still use a const char *
literal and an escape sequence as its first character that indicates the length:
const char *pascal_string = "\x03foo";
It will still be null-terminated, but that probably doesn't matter.
GCC and clang (and possibly others) accept the -fpascal-strings
option which allows you to declare pascal-style string literals by having the first thing that appears in the string be a \p
, e.g. "\pfoo"
. Not exactly portable, but certainly nicer than funky macros or the runtime construction of them.
See here for more info.
You can define an array in the way you like, but note that this syntax is not adequate:
const char *s = {3, 'f', 'o', 'o'};
You need an array instead of a pointer:
const char s[] = {3, 'f', 'o', 'o'};
Note that a char
will only store numbers up to 255 (considering it's not signed) and this will be your maximum string length.
Don't expect this to work where other strings would, however. A C string is expected to terminate with a null character not only by the compiler, but by everything else.