Frage

Ist die folgende Umwandlung sicher?

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

Ich glaube nicht, die obige Umwandlung in der for Schleife sicher ist (ich denke, es ist plattformabhängig ist). Bitte korrigieren Sie mich, wenn ich falsch bin. Ich bin überrascht, weil der Code kompiliert ohne Warnungen auch geben bei der Verwendung der -Wall -pedantic Optionen in gcc kompiliert.

War es hilfreich?

Lösung

Das Ganze hat eine Chance für eine rechtliche und mehr nur einen Grund: die 2D-int Array-Objekt wird als ein Array von char Objekte neu interpretiert. Während im allgemeinen Fall Speichern Umdeutung zu undefiniertem Verhalten führt, explizit die Sprachspezifikation „Array von [mit / ohne Vorzeichen] char“ Neuinterpretationen für Objekte jeglicher Art erlaubt.

Allerdings ist ein formales Sicherheitsproblem ist immer noch da. Die Sprache bietet keine Garantie, dass jedes Bitmuster ein gültiger Wert von char Typ ist. Ihr Versuch, neu interpretiert Speicher durch char Typen lesen kann theoretisch nicht definiertes Verhalten verursachen, wenn es Falle Darstellung für char trifft. Um hier sicher zu sein, Sie haben den unsigned char Typen zu verwenden, die die einzige Art ist, die keine Trap-Darstellungen haben. Natürlich kann eine Plattform mit einem Trapping char sicher „exotische“.

aufgerufen werden

Inzwischen Ihre sizeof(a + 1) scheint keinen Sinn zu machen. a + 1 ist ein Ausdruck der int * Typ. Warum Sie würde den Zeiger Größe verwenden Ihre x Wert in diesem Fall zu erhöhen, ist mir nicht klar. Was haben Sie zu erreichen versuchen?

Was das Fehlen von Warnungen ... würde ich nicht erwarten, dass der Compiler hier alle Warnungen zu erteilen. GCC warnt oft über Typ-punning (aka Speicher Umdeutung), aber da char Neuinterpretationen explizit zugelassen sind (wie ich oben gesagt), gibt es keine Warnung hier. Darüber hinaus in der Regel explizite Casts neigen alle Warnungen zu unterdrücken, da sie eine Möglichkeit zu sagen, den Compiler, die Sie wollen tatsächlich etwas tun, unabhängig davon, wie falsch und / oder gefährlich, es könnte sein.

Andere Tipps

eine Besetzung von jedem Zeigertyp auf char * explizit durch die Sprache C erlaubt. so dass die meisten ist es in Ordnung.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

Der erste Teil ist in Ordnung x = (char*)&b[0]; Baut des Arrays ein char Zeiger auf den Anfang. Der Test ist auch in Ordnung x <= (char *)&b[9][9] wird solange x Punkte innerhalb des Arrays wahr sein.

x += sizeof(a+1) ist das iffy Teil. Auf den meist 32-Bit-CPU-Architekturen sizeof (int *) nur geschieht die gleichen wie sizeof (int) sein, so wird dieser Code wahrscheinlich Arbeit , sondern nur durch Zufall.

Ich bin sicher, was beabsichtigt war war x += sizeof(a[0]) oder x += sizeof(b[0]), aber da tatsächlich der Code tat, was beabsichtigt war, bemerkte niemand den Fehler.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top