PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ Array: sizeof falsch?


Bond2k
2009-10-04, 14:14:51
Hallo zusammen

Bin gerade daran mir C++ beizubringen. Allerdings stehe ich gerade vor einem Problem, dass ihr hoffentlich lösen könnt.

Und zwar wollte ich nur ein einfaches Array anlegen und dieses ausgeben.

Allerdings sagt er mit sizeof, es hätte 40 Felder im Array und nicht 10 wie bei der Deklaration angegeben. Könnt ihr mir sagen warum?

code:

#include <iostream> // io system
using namespace std; // default namespace

int main(int argc,char** args)
{
// Variablendefinitionen
int a[10] = {1,2,3,4,5,6,7,8,9,10};

cerr << sizeof(a) << "\n";

for (int i=0;i < sizeof(a); i++)
{

cerr << a[i] << "\n";

}

}

Ausgabe:

40
1
2
3
4
5
6
7
8
9
10
2293576
4246770
4246668
2147328000
2293624
4198987
1
2953128
2955320
-1
2293616
1984631554
4194304
2955320
0
2147328000
2293640
4199064
1
0
2293652
1986973929
2147328000
2293716
2003114427
2147328000
2010727485
0
0
2147328000

Trap
2009-10-04, 14:22:27
sizeof gibt das richtige zurück, du interpretierst es aber falsch. sizeof(int) ist 4, also ist sizeof(array von 10 ints) 40.

Markus89
2009-10-04, 14:24:10
Liegt daran, dass ein Integer 4 bytes groß ist: 10 * 4 byte = 40 bytes.

Bond2k
2009-10-04, 14:38:53
Ach so, danke euch. Hatte es gleich wie bei Java interpretiert, dass es mir die Anzahl der Elemente im Array zurückgibt.

Coda
2009-10-04, 16:05:06
Hat es einen bestimmten Grund warum du auf stderr ausgibst und nicht auf stdout?

Das was er nach dem 10. Wert ausgibt ist übrigens Müll aus dem Speicher danach ;)

Bond2k
2009-10-04, 16:57:38
Hat es einen bestimmten Grund warum du auf stderr ausgibst und nicht auf stdout?

Das was er nach dem 10. Wert ausgibt ist übrigens Müll aus dem Speicher danach ;)

Das bedeutet also, dass man über das Array hinauslesen kann, ohne eine "Out of bounce" Fehlermeldung zu bekommen?

Du meinst das "cerr"? So hatten wir das in der Schule. Gibts da einen Unterscchied?

Ach ja, gibt es sowas wie high oder low value in C++? Oder muss man den low value Hex Wert ausschreiben?

Sephiroth
2009-10-04, 17:14:43
Du meinst das "cerr"? So hatten wir das in der Schule. Gibts da einen Unterscchied?
stdin, stdout und stderr sind 3 getrennte kanäle, wobei err üblicherweise per default auf stdout zeigt. man kann aber die beiden aber gesondert umleiden, so dass man beispielsweise die normalen ausgaben des programms sieht (via stdout) und die fehler (via stdout) in eine date geschrieben werden.
kurz: stderr nur für fehlermeldungen nutzen und "normale" ausgaben mit stdout.

http://wwwcip.informatik.uni-erlangen.de/old/tree/CIP/Manuals/unix/shell/kanaele.html

Das bedeutet also, dass man über das Array hinauslesen kann, ohne eine "Out of bounce" Fehlermeldung zu bekommen?
prinzipiell ja -> buffer overrun source #1
daher immer schön die grenzen prüfen und einhalten!
die anzahl der elemente bestimmt man z.b. so

int a[10] = {1,2,3,4,5,6,7,8,9,10};
double size = sizeof(a)/sizeof(int);

Pinoccio
2009-10-04, 17:23:09
Das bedeutet also, dass man über das Array hinauslesen kann, ohne eine "Out of bounce" Fehlermeldung zu bekommen?Das ist genau die Stelle, wo JAVA-Programmierer plötzlich wissen, warum sie lieber JAVA machen. ><

mfg

Bond2k
2009-10-04, 17:32:15
Ok, vielen Dank für eure Hilfe.

Es funktioniert jetzt auch wunderbar. Wenn ich nun allerdings das ganze in eine Funktion stelle und dann das übergebene Array auf "sizeof" abfrage, kommt 1 zurück, obwohl die ganzen 10 gefüllt sind.


int binary_search(int array[10], int key) {

int start = 0;
int end = (sizeof(array)/sizeof(int)) - 1;
int mid;

return 99999999;

}

int main(int argc,char** args)
{
// Variablendefinitionen
int a[10] = {4,7,11,23,56,76,85,111,156,236};
int key = 7;
//int index = binary_search(a,key,(sizeof(a)/sizeof(int)));
int index = binary_search(a,key);
if (index != 99999999)
{
cerr << "index is " << index << " with number " << a[index] << "\n";
}
else
{
cerr << "not found.\n";
}
}

fezie
2009-10-04, 18:10:06
Ok, vielen Dank für eure Hilfe.

Es funktioniert jetzt auch wunderbar. Wenn ich nun allerdings das ganze in eine Funktion stelle und dann das übergebene Array auf "sizeof" abfrage, kommt 1 zurück, obwohl die ganzen 10 gefüllt sind.
Weil "int array[10]" in einen Pointer konvertiert wird und die sind bei einem 64bit Programm 8 byte groß. Und 8/4 -1 = 1


//int index = binary_search(a,key,(sizeof(a)/sizeof(int)));


Ich denk das ist die einzige Lösung dafür, aber bin ned so der C++ coder, mehr C und selbst da ned so erfahren.
Du kannst übrigens auch sizeof(a[0]) für sizeof(int) schreiben.
Der Compiler weiß ja was für ein Typ das erste Element eines Arrays ist.

Aquaschaf
2009-10-04, 18:38:21
Bediene dich am besten bei der STL damit es nicht mehr "low level" ist als notwendig - http://www.sgi.com/tech/stl/Vector.html

Tiamat
2009-10-04, 21:50:43
Das ist genau die Stelle, wo JAVA-Programmierer plötzlich wissen, warum sie lieber JAVA machen. ><

mfg

Das ist eins von vielen Beispielen ^^. Du hättest mal mein Gesicht sehen sollen, als ich mir n 30€ C++ Buch von Willms gekauft habe und auf den ersten Seiten folgendes zu lesen bekam, was mir jedenfalls neu war. ;D

Achtung: C++ kennt kein Else-if. Dies kann allerdings leicht durch verschachtelte else und if Klauseln nachgebildet werden.

Nach diesem Satz ist das Buch erstmal 2 Monate im Regal vergammelt, bevor ich wieder reingelesen habe.

Ich glaub wenn man die ganzen Umständlichkeiten mal auflisten würde, würde es 999:1 für Java ausgehen, wovon der eine Punkt für C++ der Performancefaktor ist ;D

Expandable
2009-10-04, 22:09:23
Genial ;)

Oid
2009-10-04, 22:40:47
Warum gibt eigentlich

int a[10]
//......
sizeof(a)


die Länge des Arrays zurück? "a" ist doch eigentlich nur ein Pointer auf das erste Element des Arrays, und sizeof sollte somit nur die Größe eines Pointers zurückgeben?!

Ich weiß, dass es so ist wie es ist. Aber mir leuchtet das gerade nicht ein irgendwie ^^.

samm
2009-10-05, 03:00:02
Ich glaub wenn man die ganzen Umständlichkeiten mal auflisten würde, würde es 999:1 für Java ausgehen, wovon der eine Punkt für C++ der Performancefaktor ist ;DUmständlich hin oder her, manchmal schreibst du Programme mit ganz spezifischen Grössen- und Performanceanforderungen, wo C die am besten kalkulierbare Möglichkeit darstellt (Assembler mal aussen vor gelassen).

Warum gibt eigentlich

int a[10]
//......
sizeof(a)

die Länge des Arrays zurück? "a" ist doch eigentlich nur ein Pointer auf das erste Element des Arrays, und sizeof sollte somit nur die Größe eines Pointers zurückgeben?!Es ist essentiell, dass nicht nur die "Grösse eines Pointers" (die Grösse einer Speicheradresse) zurückgegeben wird, sonst wären nur primitive Datentypen mögliche Operanden. Arrays, Objekte etc. könnten nicht mehr vermessen werden.

Spearhead
2009-10-05, 03:35:51
Achtung: C++ kennt kein Else-if. Dies kann allerdings leicht durch verschachtelte else und if Klauseln nachgebildet werden.


Also das Buch das du da gelesen hast wo das drinsteht ist ziemlicher Unfug...

Nachtrag: Verschachtelt? Ein


if(x)
{}
else if()
{}


ist also verschaltelt?

Tiamat
2009-10-05, 08:06:50
Moin, na in dem Fall wär das ja wie man es von else if kennt.

Ich hab da mehr son grauenhaftes Beispiel in Erinnerung

if(a)
{
..
} else
{
if(b)
{
..
}
}


Ich hab mich damals auch gefragt, ob der Author einen verarschen will und hab das ganz gegoogelt und kam dann auf folgenden Thread.

Hier (http://www.wer-weiss-was.de/theme158/article441021.html)
Wie gesagt danach ist das Buch erstmal im Regal verstaubt ;D

Im Nachhinein glaube ich, dass der Author einfach nur darauf hinweisen wollte, dass in C/C++ das Schlüsselwort "else if" nicht zur Sprache gehört, sondern durch neues if im Else Teil nachgebildet werden muss.

Der_Donnervogel
2009-10-05, 15:20:06
Das ganze mit dem else if ist schon eine sehr theoretische Frage und kein Problem bei der Programmierung (von denen es bei C/C++ genug gibt).

Ich nehme aber an, dass auch Java kein else if kennt sondern dass das nur nachgebildet wird, da es zwei getrennte Schlüsselworte sind. Ein echtes elseif wäre so etwas was es z.B. in VB.Net mit ElseIf gibt. Bei C/C++ und Java wird aber wohl einfach nur der Umstand ausgenutzt dass falls die Bedingung beim if false ist das nächste Statement hinterm else ausgeführt wird. Das dann folgende if ist ja nichts weiter als ein Statement, auch wenn ein langer Block dran hängt. Im Prinzip ist das also immer eine verschachtelte if-else Struktur, nur dass man das eben nicht einrückt, da man bei C/C++ und Java den Code ja formatieren kann wie man will.
if (a) {
} else if (b) {
} else if (c) {
}
ist aber nichts anderes als

if (a) {
} else
if (b) {
} else
if (c) {
}

Man könnte da dann noch wenn man wollte hinter dem if Klammern schreiben. Dann ist das Statement das hinter dem else steht eben kein if sondern ein Block der wiederum nur aus einem einzelnen if besteht.

if (a) {
} else {
if (b) {
} else {
if (c) {
}
}
}

Schaut zwar alles ein wenig anders aus, macht aber das selbe.

Tiamat
2009-10-05, 16:31:53
Ich weiß :D
Nur beim Lesen dieses Buchs ( Masterclass C++ von André Willms ) kam bei mir einfach der Eindruck auf, dass man von den obigen 3 Abarten else ifs zu definieren zu der obigen 3. Form genötigt wird.

Das war ganz einfach ein Fehler von dem Author, anscheinend völlig unnötig das Statement.
Stell dir vor du willst dir ne neue Programmiersprache aneignen und du ließt auf den ersten Seiten
a) Natürlich kennt XY auch else if Blöcke, wie man sie aus anderen Programmiersprachen kennt.
oder du ließt b) ACHTUNG XY kennt kein Else if. Es muss nachgebildet werden.

Da denk ich doch beim Lesen von b) net an a) ;D

Gruß
Tiamat

Xmas
2009-10-05, 19:44:32
Warum gibt eigentlich

int a[10]
//......
sizeof(a)


die Länge des Arrays zurück? "a" ist doch eigentlich nur ein Pointer auf das erste Element des Arrays[...]
Nein, a ist ein Array. Verhält sich zwar wie ein Pointer, ist aber trotzdem etwas anderes.

Der_Donnervogel
2009-10-05, 20:39:24
Das war ganz einfach ein Fehler von dem Author, anscheinend völlig unnötig das Statement.Entweder das oder er ist ein extrem starker Theoretiker. Aus Sicht der theoretischen Informatik könnte man eventuell schon in die Richtung argumentieren, dass es einen Unterschied macht ob man ein "echtes" elseif hat oder ob man das nur über "else-if" nachbildet. Das ist allerdings praktisch so irrelevant dass es in so einem Buch nichts zu suchen hat.

Da gibt es Sachen wo es wirklich unterschiedliche Interpretationen bei anderen Sprachen gibt, und somit ein Hinweis hilfreicher wäre. Beispielsweise den Unterschied und die Vor- und Nachteile von switch im Vergleich zu Select bei VB. Da ist es wirklich so, dass man abhängig von der Sprache gewisse Dinge sehr elegant lösen kann während es bei der anderen Sprache so überhaupt nicht geht (und man auf if zurückgreifen muss) und umgekehrt, obwohl sich beide Statements auf den ersten Blick sehr ähnlich sind.

mekakic
2009-10-06, 09:54:46
Warum gibt eigentlich

int a[10]
//......
sizeof(a)


die Länge des Arrays zurück? "a" ist doch eigentlich nur ein Pointer auf das erste Element des Arrays, und sizeof sollte somit nur die Größe eines Pointers zurückgeben?!

Ich weiß, dass es so ist wie es ist. Aber mir leuchtet das gerade nicht ein irgendwie ^^.

Bei sowas sieht man auch den Unterschied. sizeof(a) liefert die korrekte Länge bzw. den Speicherplatz wieder (10) wieder. sizeof(b) liefert den Speicherplatz des Pointers zurück (4/8).


char a[] = "123456789";
char * b = "123456789";

sizeof(a)
sizeof(b)

Coda
2009-10-06, 16:03:40
XMas hat doch schon die richtige Antwort gegeben. Die Semantik eines Arrays und eines Pointers ist in C++ eben nicht genau identisch.

In C würde man übrigens tatsächlich das gleiche Ergebnis wie beim Pointer bekommen, wenn ich mich richtig erinnere.

The_Invisible
2009-10-06, 17:25:11
In C würde man übrigens tatsächlich das gleiche Ergebnis wie beim Pointer bekommen, wenn ich mich richtig erinnere.

gcc 4.3.3 bestätigt das nicht :D


#include <stdio.h>
#include <stdlib.h>

int main()
{
char a[] = "123456789";
char *b = "123456789";

printf("arr: %lu\n", sizeof(a));
printf("ptr: %lu\n", sizeof(b));

return EXIT_SUCCESS;
}

out:
arr: 10
ptr: 8


mfg

noid
2009-10-06, 18:31:35
gcc 4.3.3 bestätigt das nicht :D


#include <stdio.h>
#include <stdlib.h>

int main()
{
char a[] = "123456789";
char *b = "123456789";

printf("arr: %lu\n", sizeof(a));
printf("ptr: %lu\n", sizeof(b));

return EXIT_SUCCESS;
}

out:
arr: 10
ptr: 8


mfg
Hätte da auch keinen Unterschied zu C erwartet. Aber du hast den Code mit .c endung durch gcc gejagt?

Eggcake
2009-10-06, 21:01:22
Unabhängig davon, würde ich als "Anfänger" mal die Finger von sizeof lassen...da entstehen sehr schnell Problemchen (wie man sieht :) ).

Bond2k
2009-10-06, 21:59:29
Oh mann... da bin ich ja froh. Und ich dachte schon, ich wäre der einzige der sich da schwer tut. Da ich mir allerdings C++ im Studium ausgewählt habe, werde ich es nicht einfach so aufgeben. ;)

Besten Dank nochmals für die Erklärungen.

Coda
2009-10-06, 23:08:59
gcc 4.3.3 bestätigt das nicht :D
Ja, stimmt. Auch mit -std=C89 nicht. Irgendwas hatte ich da wohl falsch im Hinterkopf :)