Frage von Kirra1, 25

wie verschiebt man array[index] mit minus (c)?

hallo

char *baeren[] = {"EISBÄR", "BRAUNBÄR", "KOALABÄR", "GRIZZLY"}; baeren[0] + 3 liefert "bär" und das ist ganz klar !!

aber was ist wenn ich baeren[0] -3 schreibe ? ich habe %s gekriegt !! wie das ??

auch hier : wenn zeichenkette_1 =TLSP_KEQAGHX

for(i=1; i<12; i+=2) zeichenkette_1[i] = zeichenkette_1[i] - 4;

wird das ergebnis in TOLL_GEMACHT wie das ?? danke im Voraus

Antwort
von sarahj, 12

Der C-Compiler sammelt alle Konstanten im Programm und packt sie hintereinander in einen Datenbereich. Da landen einerseits die Strings, als auch der bäeren-Array (der ja ein Array-von-Pointern auf Strings ist).

Die Strings selbst haben keine Größeninformation - lediglich ein 0-byte am Ende.
Auch wenn die Strings üblicherweise in der Reihenfolge des Auftretens im Quellcode hintereinander liegen, ist dies keinesfalls definiert und zwingend: theoretisch kann der Compiler die Daten in beliebiger Reihenfolge ablegen.

Vor dem EISBÄR-String liegt also irgend ein anderes Datenelement. In Deinem Fall kam da das "%s" (vermutlich von einem printf-Aufruf) zu liegen.
Da C weder die Größen der Strings kennt, noch irgendwelche Validierungen auf Pointerzugriffe macht, kannst Du dir (z.B. mit baeren[0] - 3) beliebige Pointer basteln. Solange damit eine gültige Adresse erreicht wird, ist auch ein Zugriff darüber möglich.

Auf einem anderen Rechner, oder mit einem anderen Compiler kann das Ergebnis komplett anders sein - man darf sich also auf derlei Verhalten nicht verlassen. Es bibt übrigens auch Programme, die sich durch solche Tricks Zugang zu Datenbereichen verschaffen, die sie eigentlich nicht sehen sollten: Viren und andere Schadsoftware nutzt derlei Tricks...

Leider war das in C schon immer so, und wird auch so bleiben. C ist eher als Maschinenunabhängiger Assembler (also sehr low-level) zu sehen - mit allen Vor- und Nachteilen.

Höhere Sprachen (wie Java, Python, Ruby, Scheme oder Smalltalk) haben diese Probleme nicht. In diesen sind Zugriffe außerhalb der Array-Grenzen nicht möglich, und es wird eine Exception geworfen, wenn man das macht
(und Strings sind in diesem Sinne auch Arrays. Arrays von Characters).

Der Nachteil ist natürlich, daß diese Überprüfungen ein paar Instruktionen zur Laufzeit brauchen, daher diese Sprachen etwas langsamer sind
(was aber bei den meisten Anwendungen nicht stört - insbesondere bei Programmen, die viel I/O oder Benutzerinteraktionen machen, merkt man die paar uSekunden nicht).

PS: wenn Du sehen willst, wie die Daten zu liegen kommen, schau Dir mal den Assembler-Output des Compilers an; mit "cc -S datei.c" legt er den Assembler-Output in "datei.s" ab.
Darin solltest Du die Strings finden (in .data Sektion).

Expertenantwort
von TeeTier, Community-Experte für programmieren, 10

Na, das geht ja noch! Guck dir mal die Ausgabe von folgendem Snippet an ... das grenzt doch schon an ein Wunder, oder?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char text[] = "Nluud4#iudjw#mhghq#Wdj#ehl#JI#zhjhq#Kdxvdxijdehq#qdfk$#=,";

const size_t len = strlen(text);
for (size_t i = 0; i < len; ++i) {
text[i] -= 3;
}

puts(text);

return EXIT_SUCCESS;
}

Faszinierend! :)

Kommentar von sarahj ,

Faszinierend - stimmt.

KI ist halt das Gegenteil von ND

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten