在C中,有一个很好的方法来定义长度优先,Pascal样式的字符串作为常量,所以它们可以放在ROM中吗?(我正在使用一个带有非GCC ANSI C编译器的小型嵌入式系统).
0例如,终止C字符串.{ 'f','o','o',0}.
Pascal字符串在第一个字节中具有长度,例如.{ 3,'f','o','o'}.
我可以声明一个C字符串放在ROM中:
const char *s = "foo";
Run Code Online (Sandbox Code Playgroud)
对于Pascal字符串,我可以手动指定长度:
const char s[] = {3, 'f', 'o', 'o'};
Run Code Online (Sandbox Code Playgroud)
但是,这很尴尬.有没有更好的办法?也许在预处理器中?
cyc*_*130 20
我认为以下是一个很好的解决方案,但不要忘记启用打包的结构:
#include <stdio.h>
#define DEFINE_PSTRING(var,str) const struct {unsigned char len; char content[sizeof(str)];} (var) = {sizeof(str)-1, (str)}
DEFINE_PSTRING(x, "foo");
/* Expands to following:
const struct {unsigned char len; char content[sizeof("foo")];} x = {sizeof("foo")-1, "foo"};
*/
int main(void)
{
printf("%d %s\n", x.len, x.content);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一个问题是,它在你的字符串之后添加了一个额外的NUL字节,但它可能是理想的,因为那时你也可以将它用作普通的c字符串.您还需要将其强制转换为外部库所期望的任何类型.
您仍然可以使用const char *文字和转义序列作为指示长度的第一个字符:
const char *pascal_string = "\x03foo";
Run Code Online (Sandbox Code Playgroud)
它仍将是空终止的,但这可能无关紧要.
这听起来可能有点极端,但是如果您有许多此类需要频繁更新的字符串,您可以考虑编写自己的小工具(可能是 perl 脚本?),它在主机系统上运行,使用自定义格式解析输入文件您可以根据自己的喜好进行设计并输出 .c 文件。你可以将它集成到你的 makefile 或其他任何东西中,从此过上幸福的生活:)
我正在谈论一个程序,它将转换此输入(或您喜欢的其他语法):
s = "foo";
x = "My string";
Run Code Online (Sandbox Code Playgroud)
对于这个输出,这是一个 .c 文件:
const char s[] = {3, 'f', 'o', 'o'};
const char x[] = {9, 'M', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g'};
Run Code Online (Sandbox Code Playgroud)