2010-07-27 3 views
11

ich mit einem Problem heute bin vor, wo ich wie 0x 11223344 Speicher zu einem bestimmten Muster zu ändern, so dass der gesamte Speicher aussieht (in hex):Wie memset() Speicher zu einem bestimmten Muster anstelle eines einzelnen Bytes?

1122334411223344112233441122334411223344112233441122334411223344... 

ich kann nicht herausfinden, wie man mach es mit memset(), weil es nur ein einzelnes Byte braucht, nicht 4 Bytes.

Irgendwelche Ideen?

Danke, Boda Cydo.

Antwort

3

Ein effizienter Weg wäre, den Zeiger auf einen Zeiger der benötigten Größe in Bytes zu werfen (z.B. uint32_t für 4 Bytes) und mit Ganzzahlen füllen. Es ist ein bisschen hässlich.

char buf[256] = { 0, }; 
uint32_t * p = (uint32_t *) buf, i; 

for(i = 0; i < sizeof(buf)/sizeof(* p); ++i) { 
     p[i] = 0x11223344; 
} 

Nicht getestet!

+6

Die eine Sache zu beachten ist, dass' buf' die Ausrichtungsanforderungen für a nicht erfüllen kann 'uint32_t' auf Ihrer Plattform.Wenn' buf' das Ergebnis eines 'malloc' ist, brauchen Sie sich darüber keine Gedanken zu machen, aber wenn es (als Argument) von Code übergeben wird, den Sie nicht kontrollieren, Sie Ich werde die Ausrichtung überprüfen müssen, bevor Sie auf diese Weise auf diese Weise schreiben, sonst führt dies bei einigen zu ungültigen Zugriffen Plattformen. –

+1

Eine andere Sache, auf die man achten muss, ist Endianess, wenn dies auf einem kleinen Endian-Computer ausgeführt wird und das Füllen und Lesen mit Typen mit unterschiedlichen Größen erfolgt (dh Füllen mit int aber Lesen mit char) –

+2

Dies ist nicht sehr effizient; Die Verwendung von 'memmove()' wie in meinem Beispiel ist viel, viel schneller, da es spezielle Assembler-Ops und handoptimierten Code verwendet. –

4

Sie könnten die Sequenz irgendwo einrichten und dann mit memcpy() dorthin kopieren, wo Sie es brauchen.

9

Unter OS X verwendet man dafür memset_pattern4(); Ich würde erwarten, dass andere Plattformen ähnliche APIs haben.

Ich kenne keine einfache portable Lösung, außer einfach den Puffer mit einer Schleife zu füllen (was verdammt einfach ist).

+2

Ich habe vergessen, ich könnte Schleife verwenden. Danke für das Erinnern. Versuche es jetzt mit Schleife. – bodacydo

+0

@bodacydo: lol. buchstäblich. passiert mit uns allen :( – aib

3

Nun, die normale Methode, dies zu tun die ersten vier Bytes manuell Setup ist, und dann memcpy(ptr+4, ptr, len -4)

Dadurch werden die ersten vier Bytes in den zweiten vier Bytes und kopiert dann die zweiten vier Bytes in die dritte, und so weiter.

Beachten Sie, dass dieses "normalerweise" funktioniert, aber es ist nicht garantiert, abhängig von Ihrer CPU-Architektur und Ihrer C-Laufzeitbibliothek.

+6

Das Verhalten von 'memcpy' ist undefiniert, wenn sich die Quell- und Zielpuffer überlappen. Dies wird wahrscheinlich auf einigen Plattformen funktionieren, aber es wird sicherlich nicht bei vielen anderen funktionieren. –

+1

Dies überschreibt die ersten vier Bytes mit was auch immer in den zweiten vier Bytes ist. Außerdem sollte "memcpy" nicht mit überlappenden Bereichen verwendet werden. – bstpierre

+0

Kommentieren Sie meine ursprüngliche oder editierte Nachricht. memcpy ist (dest, src, len), was ich jetzt korrekt habe.(Ich hatte es zunächst rückwärts, aber ich hatte es vor Ihrem Kommentar behoben) –

6

Recursively den Speicher kopieren, den Bereich mit dem Sie bereits als Vorlage pro Iteration gefüllt (O (log (N)):

int fillLen = ...; 
int blockSize = 4; // Size of your pattern 

memmove(dest, srcPattern, blockSize); 
char * start = dest; 
char * current = dest + blockSize; 
char * end = start + fillLen; 
while(current + blockSize < end) { 
    memmove(current, start, blockSize); 
    current += blockSize; 
    blockSize *= 2; 
} 
// fill the rest 
memmove(current, start, (int)end-current); 

[EDIT] Was ich mit „O (log bedeuten (N))“ist, dass die Laufzeit viel schneller sein wird, als wenn Sie den Speicher manuell füllen, da memmove() in der Regel spezielle verwendet, Assembler Schleifen von Hand optimiert, die schnell lodern.

+7

Es ist O (log (n)) ruft zu 'memmove', die tatsächliche Komplexität ist immer noch O (n). –

4

wenn Ihr Muster in einem wchar_t passt, können Sie wmemset() verwenden wie Sie hätten verwendet memset().

0

Die Verwendung von "memcpy" oder "memset" ist möglicherweise nicht die effiziente Methode.

Geben Sie nicht mit Schleifen wie "für" oder "während" auf, wenn lib-definierte Funktion das gleiche tut.