In C ist ...
int zahlen[]
... kein Array, sndern ein Zeiger!
Das ist für Einsteiger oft etwas missverständlich.
Zu einem Arraytypen in C gehört IMMER auch die Größe dazu.
Wenn du also ...
int zahlen[5]
... schreibst, dann gehört die "5" zum Typen dazu, und es ist ein komplett anderer und inkompatibler Typ, als würdest du ...
int zahlen[42]
... schreiben.
Ein Zeiger hingegen wird ...
int * zahlen
... oder ...
int zahlen[]
... geschrieben, im letzten Falle also OHNE Größenangabe.
Implizit werden Arrays bei der Übergabe an Funktionen in Zeiger umgewandelt.
Innerhalb deiner Funktion ...
int getNumber(int zahlen[]);
... ist also nur ein int-Zeiger OHNE Größe sichtbar.
Randbemerkung: Deshalb können "Tricks" wie ...
size_t count = sizeof(zahlen) / sizeof(* zahlen);
... innerhalb der Funktion auch gar nicht funktionieren! Aber egal.
Der herkömmliche C-Weg wäre es jetzt, neben dem Arrayzeiger zusätzlich auch die Größe explizit an die Funktion zu übergeben:
int getNumber(int * numbers, size_t size) {
int sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += numbers[i];
}
return summe;
}
Aufgerufen wird so eine Funktion wie folgt:
int nums[] = {2, 4, 8}; // int nums[3]
int x = getNumber(nums, sizeof(nums) / sizeof(* nums));
Bei der Initialisierung des Arrays kann die Größenangabe entfallen, wie sie sich (wie oben) automatisch aus dem Kontext ergibt.
Und die Größe kannst du natürlich auch direkt als Wert an deine Funktion übergeben:
int nums[7];
// ... initialisiere nums
int x = getNumber(nums, 7);
Mit dem Unterschied zwischen Arrays und Zeigern haben oft sogar langjährige Programmierer Probleme, einfach weil sie es nie richtig gelernt haben.
So, und nun zu C++, da du in deiner Frage ja von C++ sprichst. Dort gibt es nämlich noch sehr viele weitere Möglichkeiten!
Das einfachste wäre, einfach ein auto-Template zu nutzen (ab C++17):
auto getNumbers(auto & nums) {
int sum = 0;
for (auto i : nums) {
sum += i;
}
return sum;
}
Disclaimer am Rande: Der Einfachheit halber verzichte ich konsequent auf "const-Correctness" und vielen anderen Dingen, die C und vor allem C++ so bieten.
Die obige Funktion wäre normalerweise ein Einzeiler, wenn man es "richtig" machen wollte! Aber das ist jetzt nicht weiter wichtig.
Die Zweite Möglichkeit in C++ wäre ein explizites Array. Das funktioniert auch mit uralten C++-Versionen:
template <typename T, size_t N>
T getNumber(T (& nums)[N]) {
// ... Rest wie im auto-Template ...
}
Dann gibt es noch die Möglichkeit mit Typetraits ...
#include <type_traits>
template <typename T>
T getNumber(T & nums) {
int sum {};
for (size_t i {}; i < ::std::extent<T>(); ++i) {
sum += nums[i];
}
return sum;
}
Oder man nutzt von vornherein C++-Arrays, die ihre eigene Größe kennen, und nicht "vergessen" wie die C-Arraxs:
#include <algorithm>
#include <array>
int getNumber(auto & nums) {
return ::std::accumulate(nums.begin(), nums.end(), 0);
}
// ...
::std::array<int, 7> numbers { 2, 3, 5, 7, 11, 13 };
int x = getNumber(numbers);
All das kann man auch nahezu beliebig kombinieren und es gibt noch eine ganze Reihe weiterer Möglichkeiten, die hier allerdings den Rahmen sprengen würden.
Wie gesagt, die obigen Beispiele haben alle einige Mängel, weil ich den Code absichtlich kurz und einfach halten wollte. In Produktivcode würde man "const", "noexcept", "[[nodiscard]]", uvm. Schlüsselwörter und Techniken zusätzlich nutzen.
Naja, lass dich von der Informationsflut nicht erschlagen! Soooo schlimm wie es aussieht ist das alles gar nicht. :)
Viel Erfolg noch! :)