文字列タイプ
文字列リテラルを変換するには、_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作成パスカルのような文字列も終了ヌル文字が含まれていることをお勧めします。上記のコードでは、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)]; }
正しいサイズのパスカルのような構造です。
(struct {char len; char s[sizeof(X)-!!sizeof(X)]; }){ (char)(sizeof(X)-1), (X) }
は、化合物記号である。
以下では、文字列のようにパスカルにC 文字列を変換します。パスカルのような文字列としては、'\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'の配列)と互換性があると考えるように思えます。パスカルのような文字列を使って問題が解決するのは何ですか?なぜあなたはそれらを使いたいのですか? –
少なくとも、文字列はNULターミネータを保持する必要があります。したがって、最大長を254文字に減らす必要があります。少なくともあなたはconst引数として[address + 1]を渡すことでそれらを使うことができます。 –