関数パラメーターとして既知または未知のサイズの配列を渡したい場合、どの構文を使用するかについて混乱しています。
目的のためにこれらのバリアントがあるとします:
void func1(char* str) {
//print str
}
void func2(char str[]) {
//print str
}
void func3(char str[10]) {
//print str
}
これらのそれぞれを使用することの長所と短所は何ですか?
これらのバリアントはすべて同じです。 Cでは代替スペルを使用できますが、配列サイズで明示的に注釈が付けられた最後のバリアントでも、通常のポインターになります。
つまり、最後の実装でも、any sizeの配列で関数を呼び出すことができます。
void func3(char str[10]) { }
func("test"); // Works.
func("let's try something longer"); // Not a single f*ck given.
言うまでもなくnotを使用する必要があります:ユーザーに誤った安心感を与える可能性があります」)。
Henrikが言ったように、正しい方法C++ではstd::string
、std::string&
またはstd::string const&
を使用することです(オブジェクトを変更する必要があるかどうか、およびコピーしたい)。
C++では、コンパイル時に配列の長さがわかっている場合(たとえば、文字列リテラルを渡した場合)、実際にそのサイズを取得できることに注意してください。
template<unsigned int N>
void func(const char(&str)[N])
{
// Whatever...
}
int main()
{
func("test"); // Works, N is 5
}
C++では、void func4(const std::string& str)
を使用します。
これらはすべて機能的に同一です。 Cの関数に配列を渡すと、配列は暗黙的に配列の最初の要素へのポインターに変換されます。したがって、これら3つの関数は同じ出力(つまり、char
へのポインターのサイズ)を出力します。
_void func1(char* str) {
printf("sizeof str: %zu\n", sizeof str);
}
void func2(char str[]) {
printf("sizeof str: %zu\n", sizeof str);
}
void func3(char str[10]) {
printf("sizeof str: %zu\n", sizeof str);
}
_
この変換は、配列の最初の次元にのみ適用されます。 _char[42][13]
_はchar (*)[13]
に変換されます。notは_char **
_です。
_void func4(char (*str_array)[13]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
_
char (*)[13]
は_str_array
_の型です。 「13 char
sの配列へのポインター」の書き方です。これはvoid func4(char str_array[42][13]) { ... }
と書くこともできますが、異なるサイズの配列を_func4
_に渡して実験することでわかるように、42は機能的に無意味です。
C99およびC11(ただし、C89またはC++ではありません)では、サイズを可変サイズの配列にポインターを渡すことができます。サイズと一緒にサイズを渡し、サイズ識別子を_[square brackets]
_に含めます。例えば:
_void func5(size_t size, char (*str_array)[size]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
_
これは、sizechar
sの配列へのポインターを宣言します。配列にアクセスする前に、pointerを逆参照する必要があることに注意してください。上記の例では、_sizeof str_array[0]
_は、最初の要素のサイズではなく、配列のサイズに評価されます。例として、11番目の要素にアクセスするには、_(*str_array)[11]
_または_str_array[0][11]
_を使用します。
アドオンするには、ポイントで説明します。
1)皆が言ったように、それは同じです。
2)配列は、関数の引数に渡されると、ポインターに分解されます。
3)基本的な問題は、関数内の配列のサイズを見つけることです。そのためにマクロを使用できます。
#define noOfElements(v) sizeof(v)/sizeof(0[v])
int arr[100]
myfunction ( arr, noOfElements(arr))
0 [v]またはv [0]のいずれかをマクロで使用できます。最初のマクロは、noOfElementsに渡されるユーザー定義のデータ型を回避するために使用されます。
お役に立てれば。
1次元配列では、それらはすべてコンパイラーによって同じように扱われます。ただし、2次元以上の配列の場合(例:myArray[10][10]
)、配列の行/列の長さを決定するために使用できるので便利です。