Ich frage mich, warum diese Art von Code die Größe des Testarrays erhalten kann. Ich bin mit der Grammatik in der Vorlage nicht vertraut. Vielleicht könnte jemand die Bedeutung des Codes unter erklären template<typename,size_t>
. Außerdem wird auch ein Referenzlink bevorzugt.
#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
void InitDynCalls()
{
char test[20];
size_t n = dimof(test);
printf("%d", n);
}
c++
visual-c++
Schatten Unhold
quelle
quelle
std::array
oderstd::vector
...Antworten:
Das ist wirklich schwer zu erklären, aber ich werde es versuchen ...
Zunächst
dimof
wird die Dimension oder Anzahl der Elemente in einem Array angegeben. (Ich glaube, "Dimension" ist die bevorzugte Terminologie in Windows-Programmierumgebungen).Dies ist notwendig , da
C++
undC
nicht geben Sie eine native Möglichkeit , die Größe eines Arrays zu bestimmen.Oft
sizeof(myArray)
wird angenommen, dass dies funktioniert, aber das gibt Ihnen tatsächlich die Größe des Speichers und nicht die Anzahl der Elemente. Jedes Element benötigt wahrscheinlich mehr als 1 Byte Speicher!Als nächstes könnten sie es versuchen
sizeof(myArray) / sizeof(myArray[0])
. Dies würde die Größe im Speicher des Arrays ergeben, geteilt durch die Größe des ersten Elements. Es ist in Ordnung und wird häufig imC
Code verwendet. Das Hauptproblem dabei ist, dass es zu funktionieren scheint, wenn Sie einen Zeiger anstelle eines Arrays übergeben. Die Größe eines Zeigers im Speicher beträgt normalerweise 4 oder 8 Bytes, obwohl das Element, auf das er zeigt, ein Array von 1000 Elementen sein kann.Als Nächstes müssen Sie also
C++
Vorlagen verwenden, um etwas zu erzwingen, das nur für Arrays funktioniert und einen Compilerfehler für einen Zeiger ausgibt. Es sieht aus wie das:Die Vorlage funktioniert nur mit einem Array. Es wird der Typ (nicht wirklich benötigt, muss aber vorhanden sein, damit die Vorlage funktioniert) und die Größe des Arrays abgeleitet und dann die Größe zurückgegeben. Die Art und Weise, wie die Vorlage geschrieben wird, kann möglicherweise nicht mit einem Zeiger funktionieren.
Normalerweise können Sie hier aufhören, und dies ist in der C ++ Standard Libary als
std::size
.Achtung: Hier unten gelangt es in das Gebiet der haarigen Sprachanwälte.
Das ist ziemlich cool, scheitert aber immer noch in einem obskuren Randfall:
Beachten Sie, dass das Array
x
wird deklariert , aber nicht definiert . Um eine Funktion (dhArraySize
) damit aufzurufen ,x
muss definiert werden .Sie können dies nicht verknüpfen.
Der Code, den Sie in der Frage haben, ist ein Weg, um das zu umgehen. Anstatt tatsächlich eine Funktion aufzurufen, deklarieren wir eine Funktion, die ein Objekt mit genau der richtigen Größe zurückgibt . Dann wenden wir den
sizeof
Trick an.Es sieht so aus, als würden wir die Funktion aufrufen, aber es
sizeof
handelt sich lediglich um ein Konstrukt zur Kompilierungszeit, sodass die Funktion nie aufgerufen wird.Beachten Sie, dass Sie ein Array von einer Funktion nicht zurückgeben können, aber einen Verweis auf ein Array zurückgeben können.
Dann
DimofSizeHelper(myArray)
ist ein Ausdruck, dessen Typ ein Array aufN
char
s ist. Der Ausdruck muss eigentlich nicht ausführbar sein, ist aber zur Kompilierungszeit sinnvoll.Daher
sizeof(DimofSizeHelper(myArray))
wird Ihnen zum Zeitpunkt der Kompilierung mitgeteilt, welche Größe Sie erhalten würden, wenn Sie die Funktion tatsächlich aufrufen würden. Auch wenn wir es eigentlich nicht nennen.Mach dir keine Sorgen, wenn dieser letzte Block keinen Sinn ergab. Es ist ein bizarrer Trick, einen bizarren Randfall zu umgehen. Aus diesem Grund schreiben Sie diese Art von Code nicht selbst und lassen Bibliotheksimplementierer sich über diese Art von Unsinn Gedanken machen.
quelle
DimofSizeHelper
ist eine Vorlagenfunktion, die einenT(&)[N]
Parameter verwendet - auch bekannt als Referenz auf ein C-Array von N Elementen vom Typ -T
undchar (&)[N]
eine Referenz auf ein Array von N Zeichen zurückgibt . In C ++ ein char ist Byte in der Verkleidung undsizeof(char)
wird sein garantiert1
durch die Norm.n
wird die Größe des Rückgabetyps von zugewiesenDimofSizeHelper
, dersizeof(char[N])
welcher istN
.Das ist etwas verworren
und unnötig. Der übliche Weg war:Seit C ++ 17 ist dies ebenfalls nicht
std::size
erforderlich , da wir dies tun , jedoch auf allgemeinere Weise, um die Größe eines beliebigen stl-Containers ermitteln zu können.Wie von BoBTFish hervorgehoben, ist dies für einen Randfall erforderlich.
quelle
std::extent
seit C ++ 11 die Kompilierungszeit.