将字符串转换为 pascal 字符串类型
要转换一个字符串字面量, _Generic
and 复合文字将接近OP目标。
为了获得更好的解决方案,更多细节和示例用例将有助于说明 OP 的目标。
#define P_STRING_CONV(X) _Generic((X)+0, \
char *: &((struct {char len; char s[sizeof(X)-1]; }){ (char)(sizeof(X)-1), (X) }).len \
)
void dump(const char *s) {
unsigned length = (unsigned char) *s++;
printf("L:%u \"", length);
while (length--) {
printf("%c", *s++);
}
printf("\"\n");
}
int main(void) {
dump(P_STRING_CONV(""));
dump(P_STRING_CONV("A"));
dump(P_STRING_CONV("AB"));
dump(P_STRING_CONV("ABC"));
return 0;
}
Output
L:0 ""
L:1 "A"
L:2 "AB"
L:3 "ABC"
@乔纳森莱夫勒建议创建的类似 pascal 的字符串也包含终止符空字符。要使用上面的代码执行此操作,只需进行简单的更改sizeof(X)-1
into sizeof(X)
。然后通过访问pascal_like_string + 1
,代码有一个指向有效 C 字符串的指针。
(X)+0
将数组类型转换为指针
sizeof(X)-!!sizeof(X)
生成字符串文字的大小,不计算其 \0。至少 1 个。
struct {char len; char s[sizeof(X)-!!sizeof(X)]; }
是一个大小合适的类似帕斯卡的结构。
(struct {char len; char s[sizeof(X)-!!sizeof(X)]; }){ (char)(sizeof(X)-1), (X) }
is a 复合文字.
下面将转换一个Cstring到类似帕斯卡的字符串。请注意,作为类似帕斯卡的字符串,没有'\0'
.
#include <limits.h>
#include <stdlib.h>
#include <string.h>
char *pstring_convert(char *s) {
size_t len = strlen(s);
assert(len <= UCHAR_MAX);
memmove(s+1, s, len);
s[0] = (char) (unsigned char) len;
return s;
}