Macht der C-standard erlauben die Zuweisung eines beliebigen Wertes zu einem Zeiger und der Inkrementierung es?

Ist das Verhalten von diesem code definiert?

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    void *ptr = (char *)0x01;
    size_t val;

    ptr = (char *)ptr + 1;
    val = (size_t)(uintptr_t)ptr;

    printf("%zu\n", val);
    return 0;
}

Meine ich, können wir das zuweisen einer festen Zahl zu einem Zeiger und der Schrittweite, auch wenn es auf einigen zufälligen Adresse? (Ich weiß, dass kann man nicht dereferenzieren es)

  • Haben Sie versuchen, zu kompilieren und laufen lassen?
  • Der Zeiger-Wert ist nur ein Wert, gespeichert in einem Speicher, und Sie können rechnen mit ihm. Wenn Sie versuchen, Rücksicht, es ist dann nur der Wert wird interpretiert als ein Speicher.
  • Kaum ein test von code Gültigkeit. Viel code mit undefiniertem Verhalten "kompiliert und ausgeführt wird".
  • Warum würden Sie wollen, dies zu tun?
  • nur weil der code kompiliert nicht unbedingt, dass es gut definiert Verhalten.
  • ChristianGibbons '... und es laufen'. In Anbetracht der print-Anweisung, es sollten, drucken Sie den Wert 2. Das ist die wohldefiniertes Verhalten überprüfen, mit der rechten gibt. Wenn es druckt nichts anderes, als 2 nicht klar definiert.
  • Welchen Teil von "undefiniert" ist nicht klar? Undefined bedeutet nicht, dass "unerwartete Ergebnisse". Es kann scheinen zu gut funktionieren seit Jahren. Das ist das problem.
  • In Anbetracht der print-Anweisung, es sollten, drucken Sie den Wert 2. Das ist die wohldefiniertes Verhalten überprüfen, mit der rechten gibt. Ich werde direkt zum Punkt: diese Aussage von dir zeigt einen vollständigen Mangel an Verständnis von "undefiniertem Verhalten". "Ich lief, und es auch ausgegeben die Ausgabe, die ich erwartet" sicherlich schließt nicht aus, dass Undefiniertes Verhalten.
  • In anderen Worten, nicht definiertes Verhalten in etwa bedeutet, dass die Spezifikation nicht angeben, was passieren soll. In der Tat, IIRC die Spezifikation definiert, dass jedes Programm mit undefinierten Verhalten kompilieren können, was der compiler will, da es nicht definiert. Gehören beide "kompiliert die perfekt zu den Anweisungen, die Sie erwartet/wanted", aber auch "kompiliert Code in code, der nur druckt 2" und auch "nicht kompiliert". Etwas zu tun, was Sie erwarten können, noch nicht definiertes Verhalten.
  • Unter den Verhaltensweisen, die fallen unter die Beschreibung "undefined" Verhalten "tun genau das, was Sie erwarten, wenn Sie testen wollen, und dann tun Sie etwas ganz anderes, wenn Sie etwas tun, wichtig und/oder überzeugt sich selbst, dass dies nie die Ursache des bugs, die Sie finden".
  • Es ist wirklich, obwohl. Nicht. Wenn Sie haben keine andere Wahl, Sie werden viel glücklicher sein, nicht zu tun, freche Dinge mit Ihnen, und wenn Sie nicht, können Sie wahrscheinlich abstrahieren hinter ein paar Funktionen, damit du wenigstens versuchen nicht, um herauszufinden, ((void(*)(char*))0x20000EE0)("Hello, World!") wenn, dass wäre genauso gut gewesen puts. Das heißt, diese Frage ist sinnvoll, akademisch, es ist gut, zu wissen, was UB/IDB.
  • Code mit Undefiniertem Verhalten ist einfach gebrochen. Kein "wenn"s, die "aber"s oder-nichts - falsch, gebrochen, Punkt. Es mag scheinen, zu tun, was du erwartest jetzt aber ändern-compiler oder compiler-version oder compiler-flags oder OS oder upgrade eine dynamische Bibliothek oder viele andere Dinge, und Sie können sehen plötzlich völlig anders Verhalten. Sie brach die Regeln der Sprache und nicht mehr irgendwelche Garantien auf das, was passieren wird.
  • Dies wird manchmal als "Umsetzung-nicht definiert": es ist die Implementierung definiertes Verhalten, und je nach genau das, was die Implementierung definiert, die follow-up-code möglicherweise oder möglicherweise nicht UB
  • Auch unter Ihnen sind "nachweislich dokumentiert fashion Merkmal der Umwelt". Die Autoren des Standard haben ausdrücklich anerkannt, dass viel von der Nützlichkeit der Sprache kommt von der Tatsache, dass Implementierungen zulassen, die nicht-portable Programme, um Dinge zu tun, die portable Programme nicht können. Sie erwarteten, dass compiler-Schreiber erkennen würden, dass eine hochwertige Umsetzung vorgesehen für low-level-Programmierung auf einer Plattform aussetzen sollte charakteristische Verhaltensweisen, die Plattform, auch wenn die Implementierungen, welche nicht bestimmt sind, geeignet zu sein für solche Zwecke brauchen nicht so.
  • Die Autoren der Norm explizit zu erkennen in der Begründung an, dass eine Umsetzung könnte erfüllen die Anforderungen der Standard-und doch von so geringer Qualität, wie Sie werden im wesentlichen nutzlos. Wäre es nicht möglich, für etwas, was eine Qualität-Implementierung eignet sich für viele Zwecke ist ohne verhält sich vorhersehbar in einigen Fällen, wo die Norm enthält keine Anforderungen, und die Tatsache, dass code für einen bestimmten Zweck wird nicht arbeiten auf etwas anderes als Qualität der Implementierungen, die geeignet sind für diesen Zweck sollte wohl kaum als Mangel angesehen werden.
  • Leider, die Autoren der Standard-Gedanke compiler-Schreiber erkennen würden, dass die Qualität Implementierungen vorgesehen für bestimmte Ziele und Felder der Anwendung müssen (um die Qualität Implementierungen geeignet für diese Zwecke) erwartungsgemäß Verhalten in Fällen, die über jene hinausgehen, die im Auftrag der Standard, ohne den Standard zu müssen ausdrücklich sagen, solche Dinge. Niemand hielt es für nötig, um explizit zu dokumentieren, dass Compiler Verhalten sich sinnvoll in Fällen, wenn, könnte es natürlich sinnvoll, auf den Plattformen, wo Verhalten sinnvoll wäre einfacher und leichter als etwas anderes zu tun.
  • das ist toll, ein toller Kommentar zu versichern, die Programmierer in Nischen-domains, die wissen, wie Sie mit den features, die Ihre compiler-Hersteller garantiert, dass bestimmte Verhalten. Aber es ist ein unglaublich schlechtes Kommentar zu machen in einer Diskussion, wo die Leute denken, "es habe es einmal in ein künstliches Spielzeug-problem" ist der gold-standard für die Bestimmung konsistentes Verhalten.
  • Das problem ist "vernünftig Verhalten" liegt im Auge des Betrachters. Zum Beispiel, ist es natürlich sinnvoll für Compiler zu emittieren effizienten code für alle sinnvollen Eingaben, und denke, dass ist das einzig sinnvolle Verhalten. Andere scheinen, es zu finden mehr sinnvoll für Compiler zu emittieren ineffizient code, wenn das ist, was erforderlich ist, um produzieren spezifische Müll Ausgänge aus Abfall-input.
  • Auf jeder compiler geeignet für low-level oder Systeme, Programmierung, lvalue liest und schreibt wird das Natürliche Verhalten definiert, in Bezug auf die Umwandlung eines Musters von bits, die einen Wert eines gegebenen Typs ist, oder konvertieren Sie einen Wert eines bestimmten Typs in einem Muster von bits. Während eine Umsetzung geeignet sein können für low-level-Programmierung ohne Verhalten sich in diesem Mode in allen nur denkbaren Umständen, jemanden sucht, eine Qualität zu produzieren Implementierung geeignet für low-level-Programmierung zu unterstützen Semantik, die erzielbar wären mit einem solchen Verhalten, und sollten bei der praktischen...
  • ...versuchen Sie Verhalten sich in diesem Mode in nicht-erfundene Fälle, in denen es wahrscheinlich egal ist (wenn die Kunden beschweren sich über die Fälle, wo es nicht, das ist ein ziemlich gutes Zeichen, dass die Fälle nicht egal). Ich würd Hinsicht ein compiler, der könnte sicher Unterstützung von einem leicht erkennbaren 90% von low-level-Programme, während das erreichen 80% der theoretisch erzielbaren Optimierungen wie überlegen man, die konnte nicht zuverlässig unterstützt viele low-level Programme ohne deaktivieren fast alle Optimierungen.
  • Etwas weiter gefasst, die meisten Programme haben eine Allgemeine Anforderung "gegeben, Wenn gültige Eingabe Gültiger Ausgang; wenn gegeben ungültige Eingabe verzichten, der den Start von Atomraketen". Eine gute Sprache sollte ermöglichen, ein Programmierer, um erfüllen sowohl die Anforderungen als auch ohne viel mehr Aufwand, als notwendig wäre, sich zu treffen nur das erste mal. Viele "Optimierungen" dass Implementierungen zur Verbesserung der code-Effizienz, erfüllt nur die erste Voraussetzung, aber auf Kosten der Erhöhung der Menge der Arbeit, die Programmierer tun müssen, um die zweite, und in vielen Fällen die Verringerung der Effizienz solcher code.

Schreibe einen Kommentar