web-dev-qa-db-ja.com

Cプリプロセッサでstrlen?

[〜#〜] c [〜#〜]プリプロセッサにstrlen()を実装することは可能ですか?

与えられた:

#define MYSTRING "bob"

プリプロセッサマクロXはありますか?

#define MYSTRING_LEN X(MYSTRING)
30
Joby Taffey

プリプロセッサは使用しませんが、sizeofはコンパイル時に解決されます。文字列が配列内にある場合、それを使用してコンパイル時にその長さを決定できます。

_static const char string[] = "bob";
#define STRLEN(s) (sizeof(s)/sizeof(s[0]))
_

上記のSTRLENには、strlen()とは異なり、nullターミネータが含まれることに注意してください。

36
nmichaels

はい:#define MYSTRING_LEN(s) strlen(s)

ほとんどのコンパイラでは、これは定数引数のコンパイル時定数を生成します...そして、それ以上のことはできません。

つまり、マクロは不要で、strlenを使用するだけです。コンパイラーはあなたのために仕事をするのに十分スマートです。

5
Jim Balter

できるよ:

#define MYSTRING sizeof("bob")

末尾にヌルが追加されているため、私のマシンでは4になります。

もちろん、これは文字列定数に対してのみ機能します。


MSVC 16(cl.exe -Wall /TC file.c) この:

#include "stdio.h"
#define LEN_CONST(x) sizeof(x)

int main(void)
{
    printf("Size: %d\n", LEN_CONST("Hej mannen"));

    return 0;
}

出力:

Size: 11

文字列とNUL文字のサイズ。

5
Skurmedel

一般に、Cプリプロセッサは実際にはデータを変換せず、置き換えるだけです。つまり、Cプリプロセッサの名前空間を、データ実装(機能的)永続データ構造で汚染すると、そのような操作を実行できる可能性があります。

とはいえ、文字列以外の何かを渡すと、「追加された」機能全体が見事に失敗するので、実際にはこれを実行する必要はありません。 Cプリプロセッサには、データ型の概念も、メモリの逆参照の概念もありません(変数に格納されている文字列の長さが必要な場合に役立ちます)。基本的には、「どれだけ遠くまで行けるか」という楽しい演習ですが、最終的には、MYSTRING_LENがあり、目標までの距離はわずかです。

さらに、Cプリプロセッサには名前空間がないため、このようなマクロ拡張システムを含めることができません。生成された名前が他の有用なマクロに干渉しないように注意する必要があります。最終的には、プリプロセッサは「ユニット」トークンに変換される各文字の名前と「ユニット」トークンごとに、最終的な10進表記に圧縮されます。

0
Edwin Buck