C sizeof()-Operator spinnt?

@foggy80: nein, das ist schon richtig so. du legst einen pointer vom typ char an und weist diesem einen speicherbereich zu. es wäre allerdings möglich, ein array (auf dem stack) anzulegen, das mit speicheradressen (pointern) gefüllt wird, die wiederum auf eine adresse auf dem heap verweisen. aber das soll dich mal nicht stören.

einfache merkregel: variablen, die nicht via malloc initialisiert werden, landen auf dem stack (stichwort: lokale variable). das gilt genauso für arrays. sobald die funktion beendet ist, wird der speicher, der zu beginn der funktion reserviert worden ist, wieder freigegeben, d.h. die variablen existieren de facto nicht mehr (vgl. keyword auto). ausnahme: wenn eine variable mit static deklariert wird, landet diese nicht auf dem stack, sondern im datensegment, ist im prinzip also eine globale variable. die funktion alloca funktioniert übrigens genau auf diese weise.

rufst du malloc auf, musst du dich selbst darum kümmern, den speicher auch wieder freizugeben. dafür kannst du diese so angelegten variablen über beliebige funktionsaufrufe über die gesamte laufzeit werden, solange du die speicheradresse (den pointer) nicht verlierst. außerdem bist du nicht an die begrenzte größe des stacks gebunden, sondern kannst bis zum maximum der erlaubten heapgröße speicher anfordern. wenn du linux verwendest, kannst du mit folgendem kommando diverse limits abrufen und auch ändern:

Code:
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

interessant ist insbesondere der wert bei stack size. man sieht deutlich, dass der stack hier mit seinen standardmäßigen 8 MB in der größe doch recht begrenzt ist im vergleich zum heap (auf 32 bit-systemen iirc 2 GB / prozess).
Ergänzung ()

hast du mal versucht, diesen code genau so zu kompilieren? das funktioniert so nicht, aus gutem grund:

Code:
error: invalid initializer
 
@foggy80: Das ist kein Array, sondern ein Speicherbereich ;) Oder von mir aus ein dynamisches Array.

Und wie ich bereit sagte, es muss char *tabelle = malloc(...) heissen, nicht tabelle[]
 
@ Maekloev: Du bist besser als mein bestes Buch. Danke :D

ja wenn ich dann
Code:
char *tabelle[] = (char *)malloc(10)

mache, was ist das dann? wofür brauch ich das?

da kann ich doch gleich
Code:
char *tabelle = (char *)malloc(10)
machen.
 
Das erste ist immernoch für gar nichts gut.
 
Zuletzt bearbeitet:
hier nochmal ein paar links zum thema pointer:
http://www.youtube.com/watch?v=6pmWojisM_E (nerdiges standardvideo, aber didaktisch gar nicht schlecht aufbereitet)
http://cslibrary.stanford.edu/106/
http://openbook.galileocomputing.de...r_009.htm##mjee28a882ef9125d2c4cc49121b2c65c1
http://www.cs.cf.ac.uk/Dave/C/node12.html
Ergänzung ()

und keine sorge: das konzept der zeiger sorgt häufig für kopfzerbrechen. das braucht schon seine zeit, bis man den dreh wirklich raus hat. nur geduld. ;-)
 
@bu: es geht mir auch weniger darum wofür das gut ist sondern eher was das eigentlich ist. also es ist ein zeiger. aber das wäre es ohne das [] auch.

@Maekloev: das video ist super :D C von A bis Z hab ich als Buch, den von dir vorgeschlagenen Kapitel hab ich während der konversation mehrere male gelesen^^. Die anderen Links schau ich mir auch mal an. Danke!
 
Code:
char *tabelle[] = (char *)malloc(10)

Ist kein zulässiger Code und daher, für gar nix gut.
 
achso, ich dachte dass du behauptet hättest dass es sowas geben würde...hab das was du geschrieben hast aber nochmal durchgelesen und musste dabei feststellen dass ich dich missverstanden hatte. ich hab mir schon die phantasievollsten dinge ausgemalt was es bedeuten könnte...
 
hier noch ein paar ältere unterlagen mit übungsaufgaben zum thema c. vielleicht ist da was brauchbares für dich dabei.
 

Anhänge

Nein, per malloc() wird kein Array erstellt, sondern ein zusammenhängender Speicherbereich, den kann man natürlich aber durch Pointerarithmetik natürlich wie ein Array nutzen.
Das ist ja der große Unterschied in deinem initialen Beispiel.
 
Wie ice-breaker schon sagt, du kannst es einfach wie ein Array verwenden:

Code:
char *tabelle = (char*) malloc(10);
tabelle[0] = 'h';
tabelle[1] = 'i';

// oder auch so
*(array + 0) = 'h';
*(array + 1) = 'i';
 
5.3.3 Sizeof [expr.sizeof]
1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is
either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id. The sizeof
operator shall not be applied to an expression that has function or incomplete type, to an enumeration
type whose underlying type is not fixed before all its enumerators have been declared, to the parenthesized
name of such types, or to an lvalue that designates a bit-field. sizeof(char), sizeof(signed char) and
sizeof(unsigned char) are 1. The result of sizeof applied to any other fundamental type (3.9.1) is
implementation-defined. [ Note: in particular, sizeof(bool), sizeof(char16_t), sizeof(char32_t), and
sizeof(wchar_t) are implementation-defined.74 —end note ] [ Note: See 1.7 for the definition of byte
and 3.9 for the definition of object representation. —end note ]
2 When applied to a reference or a reference type, the result is the size of the referenced type. When applied
to a class, the result is the number of bytes in an object of that class including any padding required for
placing objects of that type in an array. The size of a most derived class shall be greater than zero (1.8).
The result of applying sizeof to a base class subobject is the size of the base class type.75 When applied
to an array, the result is the total number of bytes in the array. This implies that the size of an array of n
elements is n times the size of an element.

3 The sizeof operator can be applied to a pointer to a function, but shall not be applied directly to a function.
4 The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are not
applied to the operand of sizeof.
5 The identifier in a sizeof... expression shall name a parameter pack. The sizeof... operator yields the
number of arguments provided for the parameter pack identifier. The parameter pack is expanded (14.5.3)
by the sizeof... operator. [ Example:
template<class... Types>
struct count {
static const std::size_t value = sizeof...(Types);
};
—end example ]
6 The result of sizeof and sizeof... is a constant of type std::size_t. [ Note: std::size_t is defined in
the standard header <cstddef> (18.2). —end note

Beantwortet das die Frage?

(Quelle ist übrigens der C++ Standard. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3092.pdf)
 
Vielleicht nochmal, um zur allgemeinen Verwirrung beizutragen *g*

Ein Array ist ein zusammenhängendes Stück Speicher auf dem Stack - aber es wird in den allermeisten Fällen implizit in einen Pointer auf sein erstes Element umgewandelt, damit man damit auch arbeiten kann. (die sog. Array-To-Pointer-Conversion) Eine Ausnahme dieser Regel hast du schon kennengelernt, den sizeof-Operator. ;)

Übrigens, solche Konstrukte hier:
Code:
void f( int a[10]);
void g( int a[]);
sind äquivalent mit
Code:
void h( int* a);
Tatsächlich wird an eine Funktion immer ein Pointer übergeben, niemals ein Array (der Compiler macht daraus die Pointer-Form und das Array wird beim Aufruf via Array-To-Pointer-Conversion in einen Pointer umgewandelt). Deshalb wirst du bei einem als Funktionsparameter übergebenem Array immer die Größe eines Pointers erhalten, selbst wenn in der Definition/Deklaration etwas steht wie int a[10];.

Die Gründe dafür sind etwas länger, deshalb lasse ich sie hier mal weg (denk z.B. mal über den Speicherverbrauch bei Rekursion und den doch ziemlich kleinen Stack nach).
 
Zuletzt bearbeitet:
7H3 N4C3R schrieb:
Vielleicht nochmal, um zur allgemeinen Verwirrung beizutragen *g*

Ein Array ist ein zusammenhängendes Stück Speicher auf dem Stack - aber es wird in den allermeisten Fällen implizit in einen Pointer auf sein erstes Element umgewandelt, damit man damit auch arbeiten kann. (die sog. Array-To-Pointer-Conversion) Eine Ausnahme dieser Regel hast du schon kennengelernt, den sizeof-Operator. ;)

Zusammenhängend ja, auf dem Stack jein. Kann auch im Heap oder in anderen Speichersektionen liegen.
 
Foggy, deine Verwirrung scheint daher zu stammen, daß du meinst Arrays und Pointer wären das selbe. Das ist eben nicht der Fall.

Pointer und Arrays sind NICHT das selbe. Arrays "zerfallen" nur bei der ersten Gelegenheit zu Pointern (das heißt z.B. wenn du versuchst, ein Array an eine Funktion zu übergeben). Und jetzt alle zusammen:


"Arrays sind keine Pointer."
;)
 
Damit die Verwirrung perfekt ist, hat das mal jemand von euch compiliert?

Code:
int a[5] = { 1, 2, 3, 4, 5};
int b = 2;

printf( "%d\n", a[b] );
printf( "%d\n", b[a] );

Funktioniert hier (VC++) einwandfrei und zeigt auf, dass Compiler Arrays im Endeffekt wieder wie Pointer behandeln. :)

SCNR.

j o e
 
Zurück
Oben