Was ist ein nullterminierter String?

Lesezeit: 1 Minute

[*]
lhj7362

Wie unterscheidet es sich von std::string?

  • Was ist eine “normale” Saite?

    – mmx

    10. Januar 2010 um 14:12 Uhr

  • std::string Wie auch immer, ich habe bereits eine Antwort bekommen, thx.

    – lhj7362

    10. Januar 2010 um 14:15 Uhr


Ein “String” ist wirklich nur ein Array von charS; Eine nullterminierte Zeichenfolge ist eine Zeichenfolge, in der ein Nullzeichen enthalten ist '\0' markiert das Ende des Strings (nicht unbedingt das Ende des Arrays). Alle Zeichenfolgen im Code (durch doppelte Anführungszeichen getrennt "") werden vom Compiler automatisch nullterminiert.

Also zum Beispiel "hi" ist das gleiche wie {'h', 'i', '\0'}.

  • Viel besser zu verstehen als die akzeptierte Antwort. +1

    – Mike

    17. April 2015 um 21:39 Uhr

  • Es könnte erwähnenswert sein, dass Compiler nach dem Nullzeichen suchen, um die Länge des Strings zu bestimmen.

    – Jason Stallings

    15. Juli 2015 um 13:56 Uhr

  • Ich habe eine String-Temp, und ich habe a, b, c als Temp gespeichert[0]Temp[1] und Temp[2]. Wenn ich jetzt “cout << temp" mache, gibt es nicht - "abc". Was soll ich machen? Ich habe erfahren, dass '\0' hier auch nicht als String-Terminator funktioniert.

    – Bhavuk Mathur

    23. August 2016 um 0:57 Uhr

  • @BhavukMathur öffne eine neue Frage und stelle ein Testbeispiel des Codes bereit, jemand wird dir dann helfen. Kommentare sind für Kommentare.

    – Rachitis

    24. August 2016 um 12:38 Uhr

  • Hast du darauf eine Antwort gefunden?

    – NovusMobile

    2. Februar 2018 um 21:15 Uhr

Ein nullterminierter String ist eine zusammenhängende Folge von Zeichen, deren letztes das binäre Bitmuster alle Nullen hat. Ich bin mir nicht sicher, was Sie mit einer “üblichen Zeichenfolge” meinen, aber wenn Sie meinen std::stringdann ein std::string ist nicht nötig (bis C++11) zusammenhängend sein und muss kein Abschlusszeichen haben. Auch ein std::stringDie Zeichenfolgendaten von werden immer von zugewiesen und verwaltet std::string Objekt, das es enthält; Für eine nullterminierte Zeichenfolge gibt es keinen solchen Container, und Sie verweisen auf solche Zeichenfolgen normalerweise mit bloßen Zeigern und verwalten sie.

All dies sollte wirklich in jedem anständigen C++-Lehrbuch behandelt werden – ich empfehle, es zu besorgen Beschleunigtes C++einer der besten von ihnen.

  • Grundsätzlich bestimmt das genullte Byte die Länge einer Zeichenkette in C.

    – Costique

    10. Januar 2010 um 14:08 Uhr

  • Das letzte Zeichen muss nicht das Bitmuster aus lauter Nullen haben, es muss lediglich das haben Wert von 0.

    – Avakar

    10. Januar 2010 um 14:10 Uhr


  • Mir ist keine Plattform bekannt, wo es diese Unterscheidung gibt. Beachten Sie, dass sich die Verwendung von null (oder vielleicht besser NUL) als String-Terminator vom NULL-Zeiger unterscheidet.

    anon

    10. Januar 2010 um 14:14 Uhr

  • Ich auch nicht. Allerdings sagt der Standard sehr wenig über Bitmuster ganzzahliger Werte aus.

    – Avakar

    10. Januar 2010 um 14:23 Uhr

  • Sie sagen, dass std::string kein Abschlusszeichen haben muss. Bedeutet das, dass mystring.c_str() nicht garantiert nullterminiert ist?

    – GestapeltSchief

    10. Januar 2010 um 15:20 Uhr

1646922612 268 Was ist ein nullterminierter String
Steve Jessop

Es gibt zwei Möglichkeiten, eine Zeichenfolge darzustellen:

1) Eine Folge von Zeichen mit einem ASCII-Null-Zeichen, 0, am Ende. Sie können feststellen, wie lang es ist, indem Sie nach dem Abschlusszeichen suchen. Dies wird als nullterminierte Zeichenfolge oder manchmal nullterminiert bezeichnet.

2) Eine Folge von Zeichen plus ein separates Feld (entweder eine ganzzahlige Länge oder ein Zeiger auf das Ende der Zeichenfolge), um Ihnen mitzuteilen, wie lang sie ist.

Ich bin mir bei “normaler Zeichenfolge” nicht sicher, aber was ziemlich oft passiert, ist, dass das Wort “Zeichenfolge” verwendet wird, wenn es um eine bestimmte Sprache geht, um die Standarddarstellung für diese Sprache zu bezeichnen. In Java ist java.lang.String also ein Typ-2-String, also bedeutet „String“ genau das. In C bedeutet “String” wahrscheinlich einen String vom Typ 1. Der Standard ist ziemlich ausführlich, um präzise zu sein, aber die Leute wollen immer weglassen, was “offensichtlich” ist.

In C++ sind leider beide Typen Standard. std::string ist ein String vom Typ 2[*]aber von C geerbte Standardbibliotheksfunktionen arbeiten mit Strings vom Typ 1.

[*] Tatsächlich wird std::string oft als Array von Zeichen mit einem separaten Längenfeld implementiert und ein Nullterminator. Das ist so, dass die c_str() -Funktion kann implementiert werden, ohne dass die Zeichenfolgendaten jemals kopiert oder neu zugewiesen werden müssen. Ich kann mich nicht auf Anhieb erinnern, ob es legal ist, std::string zu implementieren, ohne ein Längenfeld zu speichern: Die Frage ist, welche Komplexitätsgarantien vom Standard gefordert werden. Für Container im Allgemeinen size() wird empfohlen, O(1) zu sein, muss es aber nicht sein. Selbst wenn es legal wäre, wäre eine Implementierung von std::string, die nur Null-Terminatoren verwendet, überraschend.

1646922613 22 Was ist ein nullterminierter String
4pie0

'\0' 

ist ein ASCII-Zeichen mit Code 0, Nullabschlusszeichen, Nullzeichen, NULL. Im C Sprache dient es als reserviertes Zeichen, das verwendet wird, um das Ende einer Zeichenfolge anzuzeigen. Viele Standardfunktionen wie strcpy, strlen, strcmp und andere verlassen sich darauf. Ansonsten, wenn es keine gab NULLmuss ein anderer Weg verwendet worden sein, um das Ende der Zeichenfolge zu signalisieren:

Dadurch kann die Zeichenfolge mit nur einem Byte Overhead beliebig lang sein; Die Alternative zum Speichern einer Zählung erfordert entweder eine Zeichenfolgenlängenbegrenzung von 255 oder einen Overhead von mehr als einem Byte.

von Wikipedia

C++ std::string folgt dieser anderen Konvention und ihre Daten werden durch eine Struktur namens dargestellt _Rep:

// _Rep: string representation
      //   Invariants:
      //   1. String really contains _M_length + 1 characters: due to 21.3.4
      //      must be kept null-terminated.
      //   2. _M_capacity >= _M_length
      //      Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
      //   3. _M_refcount has three states:
      //      -1: leaked, one reference, no ref-copies allowed, non-const.
      //       0: one reference, non-const.
      //     n>0: n + 1 references, operations require a lock, const.
      //   4. All fields==0 is an empty string, given the extra storage
      //      beyond-the-end for a null terminator; thus, the shared
      //      empty string representation needs no constructor.

      struct _Rep_base
      {
    size_type       _M_length;
    size_type       _M_capacity;
    _Atomic_word        _M_refcount;
      };

struct _Rep : _Rep_base
      {
    // Types:
    typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc;

    // (Public) Data members:

    // The maximum number of individual char_type elements of an
    // individual string is determined by _S_max_size. This is the
    // value that will be returned by max_size().  (Whereas npos
    // is the maximum number of bytes the allocator can allocate.)
    // If one was to divvy up the theoretical largest size string,
    // with a terminating character and m _CharT elements, it'd
    // look like this:
    // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
    // Solving for m:
    // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
    // In addition, this implementation quarters this amount.
    static const size_type  _S_max_size;
    static const _CharT _S_terminal;

    // The following storage is init'd to 0 by the linker, resulting
        // (carefully) in an empty string with one reference.
        static size_type _S_empty_rep_storage[];

        static _Rep&
        _S_empty_rep()
        { 
      // NB: Mild hack to avoid strict-aliasing warnings.  Note that
      // _S_empty_rep_storage is never modified and the punning should
      // be reasonably safe in this case.
      void* __p = reinterpret_cast<void*>(&_S_empty_rep_storage);
      return *reinterpret_cast<_Rep*>(__p);
    }

        bool
    _M_is_leaked() const
        { return this->_M_refcount < 0; }

        bool
    _M_is_shared() const
        { return this->_M_refcount > 0; }

        void
    _M_set_leaked()
        { this->_M_refcount = -1; }

        void
    _M_set_sharable()
        { this->_M_refcount = 0; }

    void
    _M_set_length_and_sharable(size_type __n)
    {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
      if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
        {
          this->_M_set_sharable();  // One reference.
          this->_M_length = __n;
          traits_type::assign(this->_M_refdata()[__n], _S_terminal);
          // grrr. (per 21.3.4)
          // You cannot leave those LWG people alone for a second.
        }
    }

    _CharT*
    _M_refdata() throw()
    { return reinterpret_cast<_CharT*>(this + 1); }

    _CharT*
    _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
    {
      return (!_M_is_leaked() && __alloc1 == __alloc2)
              ? _M_refcopy() : _M_clone(__alloc1);
    }

    // Create & Destroy
    static _Rep*
    _S_create(size_type, size_type, const _Alloc&);

    void
    _M_dispose(const _Alloc& __a)
    {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
      if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
        if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
                               -1) <= 0)
          _M_destroy(__a);
    }  // XXX MT

    void
    _M_destroy(const _Alloc&) throw();

    _CharT*
    _M_refcopy() throw()
    {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
      if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
            __gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
      return _M_refdata();
    }  // XXX MT

    _CharT*
    _M_clone(const _Alloc&, size_type __res = 0);
      };

Die tatsächlichen Daten können erhalten werden mit:

_Rep* _M_rep() const
      { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }

Dieses Code-Snippet stammt aus der Datei basic_string.h die sich auf meiner Maschine befindet usr/include/c++/4.4/bits/basic_string.h

Wie Sie sehen können, ist der Unterschied erheblich.

Eine nullterminierte Zeichenfolge bedeutet, dass das Ende Ihrer Zeichenfolge durch das Auftreten eines Nullzeichens definiert ist (alle Bits sind Null).

“Andere Saiten” müssen zB ihre eigene Länge speichern.

Was ist ein nullterminierter String
Sewa Alexejew

Ein nullterminierter String ist ein natives Stringformat in C. Stringliterale werden beispielsweise als nullterminiert implementiert. Infolgedessen geht eine ganze Menge Code (zunächst die C-Laufzeitbibliothek) davon aus, dass Zeichenfolgen nullterminiert sind.

1646922614 69 Was ist ein nullterminierter String
phyrrus9

Ein nullterminierter String (c-String) ist ein Array von Zeichen, und das letzte Element des Arrays ist ein 0x0-Wert. Der std::string ist im Wesentlichen ein Vektor, da er ein Container mit automatischer Größenanpassung für Werte ist. Es benötigt kein Null-Terminator, da es die Größe verfolgen muss, um zu wissen, wann eine Größenänderung erforderlich ist.

Ehrlich gesagt bevorzuge ich C-Strings gegenüber Standard-Strings, sie haben einfach mehr Anwendungen in den Basisbibliotheken, diejenigen mit minimalem Code und Zuweisungen, und sind deshalb schwieriger zu verwenden.

988210cookie-checkWas ist ein nullterminierter String?

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

Privacy policy