Wie initialisiert memset ein Array von Ganzzahlen mit -1?

Lesezeit: 5 Minuten

Benutzeravatar von hackks
hackt

Das manpage sagt über memset:

#include <string.h>
void *memset(void *s, int c, size_t n)

Das memset() Funktion füllt die erste n Byte des Speicherbereichs, auf den gezeigt wird s mit dem konstanten Byte c.

Es ist offensichtlich das memset kann nicht zum Initialisieren verwendet werden int Array wie unten gezeigt:

int a[10];
memset(a, 1, sizeof(a));  

es ist weil int wird durch 4 Bytes (sagen wir) dargestellt und man kann nicht den gewünschten Wert für die Ganzzahlen im Array erhalten a.
Aber ich sehe oft die Programmierer verwenden memset die einzustellen int Array-Elemente entweder 0 oder -1.

int a[10];
int b[10];
memset(a, 0, sizeof(a));  
memset(b, -1, sizeof(b));  

Nach meinem Verständnis Initialisierung mit Integer 0 ist in Ordnung, weil 0 kann in 1 Byte dargestellt werden (möglicherweise irre ich mich in diesem Zusammenhang). Aber wie ist es möglich, zu initialisieren b mit -1 (ein 4-Byte-Wert)?

  • Sie liegen etwas falsch mit dem Grund für die Initialisierung mit 0 ist in Ordnung. Es ist in Ordnung, weil 0 passt in ein unsigned char (Daher wird es nicht abgeschnitten, wenn es als zweites Argument für verwendet wird memset) und weil das Bitmuster im Speicher für a sizeof(int)-Byte Null ist identisch mit dem Bitmuster im Speicher für sizeof(int) sequentielle Ein-Byte-Nullen. Beides muss zutreffen, damit dies funktioniert. Tatsächlich gelten diese Dinge für genau zwei Zahlen in der Zweierkomplement-Arithmetik: 0 und -1.

    – zol

    22. Juli 2015 um 0:36 Uhr


  • @zwol: Hm? Der erste Satz spricht von Nullen und gilt daher nicht wörtlich für −1. Vermutlich beabsichtigen Sie also, den ersten Satz implizit zu parametrisieren: Es funktioniert für x wenn die Bits für ein int mit Wert x sind die gleichen wie die Bits für sizeof(int) unsigned char jeweils mit Wert x. Darüber hinaus müssen wir die berücksichtigen unsigned char mit Wert x als Ergebnis der Umwandlung von x zu unsigned char, da −1 nicht darstellbar ist. Wenn ja, dann ist es nicht wahr, dass 0 und −1 die einzigen solchen Werte sind. 16.843.009 • x funktioniert für jede ganze Zahl 0 ≤ x < 256. (16.843.009 ist Hex 1010101).

    – Eric Postpischil

    27. Oktober 2020 um 17:45 Uhr


  • @zwol: Abgesehen von der Tatsache, dass C die Bitpositionen in Ganzzahlen unterschiedlicher Breite nicht benötigt, um dieselben Werte darzustellen.

    – Eric Postpischil

    27. Oktober 2020 um 17:48 Uhr

  • @EricPostpischil Ich verstehe dein Beispiel nicht. Kein Vielfaches von 16.843.009 ist durch einen der darstellbar char Typen (nun, es sei denn, Sie befinden sich auf einer Maschine, auf der CHAR_BIT >= 25.)

    – zol

    27. Oktober 2020 um 18:12 Uhr

  • @zwoll: 0x34343434 ist ein Vielfaches von 16.843.009; es ist 0x34 * 0x01010101. int a; memset(&a, 0x34343434, sizeof a); setzt jedes Byte von a zu 0x34. Dann der Wert von a wird sein 0x34343434.

    – Eric Postpischil

    27. Oktober 2020 um 18:47 Uhr


Benutzeravatar von Sergey Kalinichenko
Sergej Kalinitschenko

Seltsamerweise der Grund, warum dies funktioniert -1 ist genau derselbe wie der Grund, warum dies mit Nullen funktioniert: in Zweierkomplement binäre Darstellung, -1 hat 1s in all seinen Bits, unabhängig von der Größe der Ganzzahl, also Füllen einer Region mit Bytes, die mit all gefüllt sind 1s erzeugt eine Region von -1 unterzeichnet ints, longs, und shorts auf Zweierkomplement-Hardware.

Auf Hardware, die vom Zweierkomplement abweicht, wird das Ergebnis anders sein. Das -1 Integer-Konstante würde in eine konvertiert werden unsigned char ausgerechnet, weil die Norm konkret vorschreibt, wie die Konvertierung durchzuführen ist. Allerdings eine Region von Bytes, bei denen alle ihre Bits auf gesetzt sind 1 würden gemäß den Regeln der Plattform als integrale Werte interpretiert. Beispielsweise würden auf Vorzeichen-und-Größen-Hardware alle Elemente Ihres Arrays den kleinsten negativen Wert des entsprechenden Typs enthalten.

  • Würde nicht verwenden ~0 effektiv gleich (und klarer) sein?

    – Fiddle Bits

    13. Juni 2014 um 14:46 Uhr

  • @FiddlingBits Ja, mit ~0 würde die Verwirrung hier auf jeden Fall vermeiden.

    – Sergej Kalinitschenko

    13. Juni 2014 um 14:50 Uhr

  • @hackks Wenn Sie einen Speicherbereich, der a entspricht, mit Nur-Einsen-Bitmustern füllen sizeof von einem ganzzahligen Typ (int, longoder short) und dann diese Region als den entsprechenden ganzzahligen Typ neu interpretieren, würden Sie sehen -1 auf Computern mit Zweierkomplementdarstellung. Beachten Sie, dass Sie in seltenen Fällen, wenn Sie eine Hardware mit Vorzeichengröße haben, die kleinste negative Ganzzahl sehen, die auf dieser Hardware darstellbar ist (ich habe solche Hardware noch nie gesehen, oder sogar eine Person, die erwähnt hat, dass sie solche Hardware gesehen hat, aber ich habe gehört, dass sie existiert) .

    – Sergej Kalinitschenko

    13. Juni 2014 um 15:08 Uhr

  • @hackks Du hast recht, mit -1 als “Abkürzung” für ein “Byte gefüllt mit allen Einsen” ist plattformspezifisch. Ich habe einige Klarstellungen hinzugefügt, zusammen mit dem langen Kommentar oben. Vielen Dank!

    – Sergej Kalinitschenko

    13. Juni 2014 um 15:23 Uhr

  • @chux Der Standard sagt das, um einen negativen ganzzahligen Wert umzuwandeln unsigned Der Compiler muss die Größe des negativen Werts von 2^N subtrahieren, wobei N die Anzahl der Bits im ganzzahligen Typ ohne Vorzeichen ist. Hier ist N 8, also ist das Ergebnis 256-1=255, ein vorzeichenloser Wert. Auf diese Weise vermieden sie, dass die Prozessimplementierung definiert wurde, ohne dass eine Zweierkomplementdarstellung erforderlich war. Deshalb ist mein Verständnis so -1 unabhängig davon, wie die Negative auf der Zielplattform dargestellt werden, in ein Nur-Einsen-Bitmuster umgewandelt.

    – Sergej Kalinitschenko

    13. Juni 2014 um 18:44 Uhr


Benutzeravatar von Minhas Kamal
Minhas Kamal

Wenn alle Bits einer Zahl sind 0sein Wert ist auch 0. Allerdings, wenn alle Bits sind 1 der Wert ist -1.

Wenn wir schreiben int a[2], 4×2 Bytes Speicher werden zugewiesen, die Zufalls-/Müllbits enthalten.

00110000 00100101 11100011 11110010    11110101 10001001 00111000 00010001

Dann schreiben wir memset(a, 0, sizeof(a)). Jetzt, memset() arbeitet Byte für Byte und eine Byte-Darstellung (unsigned char) von 0 ist 00000000. Also wird es-

00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000

Daher beides a[0] und a[1] werden mit initialisiert 0.


Nun, mal sehen memset(a, -1, sizeof(a)): ein Byte für -1 ist 11111111. Und wir bekommen-

11111111 11111111 11111111 11111111    11111111 11111111 11111111 11111111

Hier beides a[0] und a[1] wird den Wert haben -1.


Allerdings z memset(a, 1, sizeof(a)): 1 in einem Byte ist 00000001

00000001 00000001 00000001 00000001    00000001 00000001 00000001 00000001

Also wird der Wert sein- 16843009.

  • void *memset( void *dest, int ch, size_t count ); => Kopiert den Wert ch (Nach Umstellung auf unsigned char) in jedes der ersten Zählzeichen des Objekts, auf das gezeigt wird dest.

    – Minhas Kamal

    27. Oktober 2020 um 18:23 Uhr

1414800cookie-checkWie initialisiert memset ein Array von Ganzzahlen mit -1?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy