11

重複の可能性:
パラメーターとして渡された配列のサイズ

次のコードの出力がなぜ 1 と 9 になるのか疑問に思っていました。これは、関数のサイズで配列が宣言されていないためですか? 「配列のサイズ」を関数に分離するにはどうすればよいですか?

#include "stdafx.h"
#include <iostream>
using namespace std;

int size(int a[])
{
    return sizeof a/sizeof a[0];
}

int main()
{   
    int a[] = {5,2,4,7,1,8,9,10,6};
    cout << size(a) << endl;
    cout << sizeof a/sizeof a[0] << endl;
    system("pause");
    return 0;
}
4

7 に答える 7

12

書き込むときsize(a)は、配列ではなくポインターを渡します。ポインタと an のサイズintは 4 または 8 (ABI に依存) であるため、sizeof(int *)/sizeof int( 32 ビット マシンの場合は4/4= 1、64 ビット マシンの場合は8/4=2 ) となり、これは1または2になります。

C++ では、配列を引数として関数に渡す場合、実際には配列へのポインターを渡しています。

于 2012-11-21T10:00:45.453 に答える
8

Maroun85の答えは正しいです。これは明らかではありませんがa、inint size(int a[])はポインターです。

しかし、なぜC++の方法でそれをしないのですか。std::vectorの使用

std::vector<int> a = {5,2,4,7,1,8,9,10,6};
cout << a.size() << endl;

ここにトリックはありません

- 編集

コンパイラが c++11 をサポートしていない場合。できるよ:

std::vector<int> a;
a.push(5);
a.push(2);
...
cout << a.size() << endl;
于 2012-11-21T10:04:34.083 に答える
6

size()配列を関数に渡すと、配列がその最初の要素へのポインターに減衰するため、関数は希望どおりに機能しません。ポインターの and sizeof演算子aへの減衰int*は、配列ではなくポインターのサイズを返します。std::vector<int>これにより、関数に渡すたびにベクトルのサイズを取得できるため、代わりにa を使用することを検討してください。

于 2012-11-21T10:00:42.373 に答える
5

配列を関数に渡すと、それらはポインターに崩壊します。したがって、size()関数は次と同等です。

int size(int* a)
{
    return sizeof a/sizeof a[0];
}

Andsizeof aはポインターのサイズであり、ここでは int のサイズと同じであるため、出力になります。

于 2012-11-21T10:01:34.857 に答える
4

配列は常にポインターによって渡されることに注意してください。

したがって、関数内aは へのポインターintであり、(32 ビット整数の場合) へのポインターのサイズはintのサイズと同じですint

于 2012-11-21T10:00:47.150 に答える
4

sizeof実行時ではなく、コンパイル時に評価されます。コンパイラは、 function に渡すものを分析しませんsizeが、関数パラメーターをポインターとして扱います。したがって、あなたの関数ではsize、 の結果はへのポインタsizeof aのサイズであり、これはシステム上の のサイズと偶然に等しくなります。intint

于 2012-11-21T10:01:19.113 に答える
4

ソリューションが機能しない理由の最良の説明は、Maroun の回答にあります。

質問の 2 番目の部分 (「どうすれば実行できますか?」) については、テンプレート関数を使用してこれを行うことができます。

template <typename T, size_t n> const size_t size(const T (&)[n]) { return n; }

もちろん、これは配列のサイズが一定である場合にのみ機能します (コンパイラから見た場合に一定です) が、とにかくこの場合にのみ機能します。配列はそのサイズをどこにも格納しないため、既知のコンパイル時定数、それを知る方法はありません。

コンパイル時の定数ではない配列(たとえば、 で割り当てるものoperator new[]、または非標準のコンパイラ拡張機能を使用するもの) を扱うためにこれが必要な場合は、サイズをどこかに明示的に格納する必要があります。

(ちなみに、私の上記のステートメントは技術的に間違っています。実際、割り当てサイズは通常保存されますが、これは依存できない、依存すべきではない実装の詳細です。)

于 2012-11-21T10:17:21.827 に答える