将字符串转换为帕斯卡字符串类型
要转换字符串文字,_Generic
和复合文字将接近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;
}
输出
L:0 ""
L:1 "A"
L:2 "AB"
L:3 "ABC"
@Jonathan Leffler建议创建类似于Pascal的串还包含一个终止空字符。要使用上述代码,请将sizeof(X)-1
简单更改为sizeof(X)
。然后通过访问pascal_like_string + 1
,代码有一个指向有效C字符串的指针。
数组类型转换为指针
sizeof(X)-!!sizeof(X)
产生大小字符串的文字,不计算其\ 0。至少1.
struct {char len; char s[sizeof(X)-!!sizeof(X)]; }
是一个正确大小的pascal状结构。
(struct {char len; char s[sizeof(X)-!!sizeof(X)]; }){ (char)(sizeof(X)-1), (X) }
是复合文字。
下面将一个C 串转换为像串帕斯卡。请注意,作为类似pascal的字符串,没有'\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;
}
1.你为什么要这样做?我认为我并不真正了解你实际想要达到什么目标。 –
主要的问题是,你似乎认为类似Pascal的字符串与C字符串(指向char的指针或char的数组)是兼容的,它实际上并不自然。使用类似Pascal的字符串会解决什么问题?你为什么要使用它们? –
至少,这些字符串应该保留一个NUL终止符,因此将它们的最大长度减少到254个字符。至少可以通过传递[address + 1]将它们用作const参数。 –