String und Arrays null terminiert?



  • In C# sind Strings ja "nicht" null terminiert. Allerdings ist der nächste Character nach einem String sehr wohl '\0'. Jetzt kam ich auf die Idee mal zu schauen, ob das auch für normale Arrays anstatt Strings gilt. Und wenn ich mich nicht vertan habe scheinen Arrays im generellen mit einer nachfolgenden Null terminiert zu sein. Kann das jemand bestätigen? Gibt es dazu einen Hinweis in der MSDN?

    Siehe hier:

    https://ideone.com/cAYibm

    Die "MatchChars" bzw. "MatchInts" Funktionen vergleichen zwei Arrays und geben "return p;" aus wenn das erste übergebene Array bzw. der erste Pointer "p" '\0' bzw. 0 wird. Da das erste Array weniger Elemente als das zweite hat hätte ich erwartet, dass im zweiten Schleifendurchlauf zufällige Werte an der Position (nun ja außerhalb des ersten Arrays) gefunden werden. Zumindest verhält sich das ganze in C++ so (Ausgabe: "return null; (2)"). Sind C# Arrays also mit einer folgenden "0" versehen?



  • @enumerator sagte in String und Arrays null terminiert?:

    Sind C# Arrays also mit einer folgenden "0" versehen?

    Arrays (C# Programming Guide):

    The default values of numeric array elements are set to zero, and reference elements are set to null.



  • Ok, aber was willst du mir damit sagen. Ich lese ja explizit über das Array hinaus... es geht also um die erste Stelle außerhalb des Arrays!



  • Sorry, die Antwort passte nicht ganz auf die Frage.

    C# Language Specification v5:

    23.6.4 Pointer element access

    A pointer-element-access consists of a primary-no-array-creation-expression followed by an expression
    enclosed in “[” and “]”.
    pointer-element-access:
    primary-no-array-creation-expression [ expression ]
    In a pointer element access of the form P[E], P shall be an expression of a pointer type other than void*,
    and E shall be an expression that can be implicitly converted to int, uint, long, or ulong.
    A pointer element access of the form P[E] is evaluated exactly as (P + E). For a description of the
    pointer indirection operator (
    ), see §23.6.2. For a description of the pointer addition operator (+), see
    §23.6.7.
    [Example: In the following code

       class Test
       {
           static void Main() {
               unsafe {
                   char* p = stackalloc char[256];
                   for (int i = 0; i < 256; i++) p[i] = (char)i;
               }
           }
       }
    

    a pointer element access is used to initialize the character buffer in a for loop. Because the operation P[E] is precisely equivalent to *(P + E), the example could equally well have been written:

       class Test
       {
           static void Main() {
               unsafe {
                   char* p = stackalloc char[256];
                   for (int i = 0; i < 256; i++) *(p + i) = (char)i;
               }
           }
       }
    

    end example]
    The pointer element access operator does not check for out-of-bounds errors and the behavior when accessing an out-of-bounds element is undefined. [Note: This is the same as C and C++. end note]

    Über magische 0-Terminierung spricht nur

    C# Language Specification v5:

    23.7 The fixed statement
    [...]
    A char* value produced by fixing a string instance always points to a null-terminated string. Within a fixed statement that obtains a pointer p to a string instance s, the pointer values ranging from p to
    p + s.Length - 1 represent addresses of the characters in the string, and the pointer value
    p + s.Length always points to a null character (the character with value '\0').



  • Ah ok, danke für die Info. Habe gerade nochmal ein Testprogramm geschrieben. Scheint wirklich nur für chars zu gelten:

    unsafe public static void Main()
    	{
    		int[] values = new int[10];
    		values[0] = 0;
    		values[1] = 1;
    		values[2] = 2;
    		values[3] = 3;
    		values[4] = 4;
    		values[5] = 5;
    		values[6] = 6;
    		values[7] = 7;
    		values[8] = 8;
    		values[9] = 9;
    		
    		fixed (int* p = values)
    		{
    		 int* p2 = p + 9;
    		 Console.WriteLine((*p2).ToString());
    		 ++p2;
    		 Console.WriteLine((*p2).ToString());
    		 ++p2;
    		 Console.WriteLine((*p2).ToString());
    		}
    		
    		Console.WriteLine("\nHello World!\n");
    		
    		char[] chars = new char[10];
    		chars[0] = '0';
    		chars[1] = '1';
    		chars[2] = '2';
    		chars[3] = '3';
    		chars[4] = '4';
    		chars[5] = '5';
    		chars[6] = '6';
    		chars[7] = '7';
    		chars[8] = '8';
    		chars[9] = '9';
    		
    		fixed (char* c = chars)
    		{
    		 char* c2 = c + 9;
    		 Console.WriteLine(((int)(*c2)).ToString());
    		 ++c2;
    		 Console.WriteLine(((int)(*c2)).ToString());
    		 ++c2;
    		 Console.WriteLine(((int)(*c2)).ToString());
    		}
    	}
    
    9
    772208824
    10949
    
    Hello World!
    
    57
    0
    0