1

私はこの質問が何度も聞かれることを知っています、そして私はコンパイル時にそれをしたのでそれをする方法を尋ねていません。私の質問はそれがどのように機能するかです。それは私が理解していないことだからです。

char[]関数にaを渡すと、その情報が失わchar*れ、テンプレートを使用してコンパイル時に文字配列のサイズを取得できないため、文字列自体を渡してみましたが、機能しました。

template <int N> inline int arr_len(const char (&)[N]) { return N - 1; }

#define STR "this is an example!"

const char *str_ptr = STR;

int main()
{
  int array_size = arr_len(STR);
}

このコードをVC++2008、Intel C ++ 12、GCC 4.7でテストしたところ、動作しました。

文字列自体を渡すことにより、コンパイラはそれをconst char[]-少なくとも私が思うもの-と見なし、文字列のサイズを取得できます。それはどのように可能ですか?

4

3 に答える 3

4

文字列リテラル型は配列であり、ポインタではありません。したがって、参照によって配列を取得する関数に直接渡す場合、ポインターに減衰しません。

于 2012-05-04T20:20:29.903 に答える
2

これは、STRがコンパイラの起動前に置き換えられるマクロであるためです。

文字列リテラル(配列ではない)である「XXXX」に置き換えられます。

これを機能させるには、次のようにします。

char const  str_ptr[] = "XXX YYY";
              //  ^^^^    Compiler works out size

int main()
{
    int array_size = arr_len(str_ptr);
                         //  ^^^^^^^ pass in an object that has a type.
};
于 2012-05-04T20:19:58.833 に答える
0

C ++では、関数のパラメータータイプが一時的に配列として識別されると、パラメータータイプは、配列の要素タイプへのポインターになるように「調整」されます。

したがって、次void foo(char c[])のように記述します。コンパイラは効果的にそれをに書き換えますvoid foo(char *c)。次に、配列を渡すと:

char x[10];
foo(x);

C ++は、引数をaにvoid foo(char *c)変換して関数を呼び出すことができることを検出して確認します。これは、まさにそれが行うことです。char []char *

ただし、関数の型に対するこの調整は、書き込まれたパラメーターの型が配列である場合にのみ発生します。配列への参照は配列ではないため、関数を宣言するときに同等の調整は実行されませんvoid bar(char (&c)[10])

あなたの質問に答えるために必要な2番目のビットは、文字列リテラルのタイプがconstcharの配列であるということです。関数呼び出しで文字列リテラルを直接記述すると、const char (&)[N]C ++を使用する関数では、「配列->最初の要素へのポインター」変換を行う代わりに、配列への参照を渡すことができることがわかります。これがその機能であり、テンプレートタイプの推定により、文字列のサイズに適した数値が検出されます。

于 2012-05-04T20:28:07.503 に答える