Forum: PC-Programmierung int-Array Initialisieren


von Karin (Gast)


Lesenswert?

Hallo Spezialisten,

wie kann ich in C++ ein Array aus int initialisieren?
wie das mit 0 für jedes Feld geht, weiß ich?
Aber wie initialisiere ich jedes Feld mit 1?

int* pArray = new int[10];
memset(pArray, 0, sizeof(int) * 10);

ergibt:
-> pArray[0] = 0
-> .
-> ..
-> pArray[9] = 0

ich will aber 1 drinstehen haben!

memset((int*)pArray, 1, 10)

dann steht aber nur Müll drin.

Kann mir jemand das erklären?

Danke Euch

Karin

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

memset beschreibt einzelne Bytes mit dem angegebenen Wert; in Deinem
ersten Falle rufst Du das auch korrekt auf, in dem Du die Anzahl der zu
beschreibenden Bytes mit "sizeof (int) * 10" bestimmst.

Dein zweiter Versuch schlägt einerseits fehl, weil Du nur die ersten
zehn Bytes des Arrays überschreibst, was, je nach sizeof (int) nur die
ersten fünf oder gar nur zweieinhalb Arrayelemente überschreibt.
Andererseits schlägt Dein Versuch fehl, weil Du den Arrayelementen
nicht den Wert 1, sondern den Wert 0x0101 (bei sizeof (int) == 2) oder
0x01010101 (bei sizeof (int) == 4) zuweist.
Das ist 257 oder 16843009.

Verständlich?

Du wirst Dein Array "von Hand" mit einer Schleife initialisieren
müssen:

  for (i = 0; i < 10; i++)
    pArray[i] = 1;

von Karin (Gast)


Lesenswert?

Danke Rufus,

ist das nicht so wie bei memcpy, daß der Cast angibt,
das der Compiler in 4er Schritten gehen soll?
Offenbar nicht, sehr performat ist das mit der Schleife dann nicht
mehr...

Karin

von OldBug (Gast)


Lesenswert?

Naja, was meinst Du denn, wie 'memset' arbeitet?

von Karin (Gast)


Lesenswert?

@OldBug:

das war ja meine Frage, danke für die Wiederholung

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nö, memset selbst erwartet einen Pointer auf einzelne Bytes.
Sieh' Dir den Prototypen an.

Da memset auch keine C++-Funktion ist, gibt es auch keine überladene
Variante für andere Pointertypen.

von OldBug (Gast)


Lesenswert?

Öhm, sorry, das ist flasch angekommen!

Also:

>sehr performat ist das mit der Schleife dann nicht
>mehr...

>Naja, was meinst Du denn, wie 'memset' arbeitet?

Aus dem Bauch heraus würde ich vermuten, daß memset in etwa so
implementiert ist:
1
void memset(void *ptr, int val, size_t size)
2
{
3
  size_t ctr = 0;
4
  for (;ctr < size; ctr++)
5
    (int *)ptr = val;
6
}

Oder so ähnlich...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Der Typecast nach (int *) ist nicht korrekt; memset arbeitet mit
einzelnen Bytes bzw. Zeichen.

von Karl H. (kbuchegg)


Lesenswert?

[Quote]
Aus dem Bauch heraus würde ich vermuten, daß memset in etwa so
implementiert ist:
void memset(void *ptr, int val, size_t size)
{
  size_t ctr = 0;
  for (;ctr < size; ctr++)
    (int *)ptr = val;
}Oder so ähnlich...
[/Quote]

Du hasst nicht aufgepasst!

memset (wie alle Mitglieder der mem...() Familie) arbeitet auf
Bytes nicht auf int!!

Also wenn memset tatsächlich mit einer Schleife implementiert ist (*),
dann ist es höchstens so implementiert:
1
memset(void *ptr, int val, size_t size)
2
{
3
  size_t ctr = 0;
4
  for (;ctr < size; ctr++)
5
    (unsigned char *)ptr = val;
6
}


(*) Viele Prozessoren stellen für solche Aufgaben eigene Instruktionen
zur Verfügung. Derjenige der Deine Standardbibliothek geschrieben hat,
weiß das aber und verwendet diese auch. Gibt es sie nicht, so kommt
halt obige Schleife zum Zug.

Im übrigen haben Funktionen aus der mem...() Familie in C++ nichts mehr
verloren, es sei dann man arbeitet auf tiefer Hardware-Ebene.
Alles andere fällt mehr in die Kategorie: fahrlässige Programmierung.

von OldBug (Gast)


Lesenswert?

Sorry, daß ich nicht aufgepasst habe ;-P

Müsste da nicht noch ein Cast rein? Und zwar vor val, auf unsigned
char?

Aber das spielt auch - wie schon bemerkt - eigentlich keine Rolle, denn
memset ist hier völlig fehl am Platze (selbst wenn man kein C++,
sondern C Programmieren würde)...

von T. Stütz (Gast)


Lesenswert?

Auf Intelbasierenden Achritekturen gibt es in Assembler einen Befehel
STOS BYTE bzw STOS WORD in Verbindung mit REP kann dann ganze
Speicherbereiche belegt werden (Store Single Byte/Wort)

AL/AX gibt den Wert vor, ES:DI zeigt auf den Beginn in CX steht die
Anzahl Bytes/Worte.

damit ist ein memset innerhalb weniger Assemblerzeilen geschrieben

Gruss

von T. Stütz (Gast)


Lesenswert?

Sorry heißt natürlich "STOre String"

von Rolf Magnus (Gast)


Lesenswert?

> Da memset auch keine C++-Funktion ist, gibt es auch keine
> überladene Variante für andere Pointertypen.

Für sowas gibt's in C++ std::fill und std::fill_n aus <algorithm>.
Damit sähe der Code aus dem Originalposting dann so aus:
1
    int* pArray = new int[10];    
2
    std::fill_n(pArray, 10, 1);

Oder noch einfacher, mit vector statt einem Array:
1
    std::vector<int> pArray(10, 1);

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.