在C中声明Pascal样式的字符串

Job*_*fey 20 c string pascal

在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字符串.您还需要将其强制转换为外部库所期望的任何类型.

  • @FilipHaglund是的,这是使用pascal字符串的一个原因.但另一个原因是告诉字符串的长度而不必扫描整个字符串.此外,许多基于C的API(例如Windows,POSIX ......)无论如何都只接受NUL终止的字符串.这就是为什么Delphi,FreePascal和类似的方法将一个空字节放在他们的pascal字符串的末尾.如果嵌入了NUL,底层(基于C)系统忽略了字符串的其余部分,这是一个潜在的陷阱.Java试图通过使用UTF-8中的2字节序列对NUL进行编码来欺骗8位C字符串API.但正确的UTF-8解码器会拒绝它. (3认同)

小智 15

GCC和clang(以及可能还有其他人)接受这个-fpascal-strings选项,允许你通过让字符串中出现的第一个东西为a来声明pascal样式的字符串文字\p,例如"\pfoo".不完全可移植,但肯定比时髦的宏或它们的运行时构造更好.

有关详细信息,请参见此处


Bla*_*iev 5

您仍然可以使用const char *文字和转义序列作为指示长度的第一个字符:

const char *pascal_string = "\x03foo";
Run Code Online (Sandbox Code Playgroud)

它仍将是空终止的,但这可能无关紧要.

  • 实际上,如果十六进制文字优于八进制,您还可以使用自动字符串文字连接行为来使用 `"\x03" "foo"` 来防止消耗额外的字符。 (3认同)
  • 是的,这会奏效.但是,我仍然需要手动保持\ x03与字节数同步,这很容易出错 (2认同)

cyc*_*130 5

这听起来可能有点极端,但是如果您有许多此类需要频繁更新的字符串,您可以考虑编写自己的小工具(可能是 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)