Gleich vorweg: Ich habe mit VB nichts am Hut.
> Frage: Wo ist der Unterschied und wie ist es im Speicher organisiert?
Ein Array ist in diesem Fall ein einfacher Speicherblock, in dem
nacheinander (indizierbar) Werte stehen.
ReDim allokiert einen neuen Block und kopiert bei Bedarf Daten aus dem
alten (Preserve). Das Ganze dient im Prinzip nur der
Rückwärtskompabilität; in VB.NET sollte man eher die generischen
Collections verwenden, z.B. List(Of T).
Auch bei einem String wird - wenn der zur Verfügung stehende
Speicherbereich komplett mit Zeichen belegt ist - ein neuer Block
allokiert, Daten werden kopiert und der alte Block wird verworfen. Nur
geschieht dies intern in der String-Klasse, so dass man sich darum nicht
kümmern muss (ähnlich wie bei 'List'). Es gibt natürlich eine Reserve -
mehr oder weniger "intelligent" bestimmt; meist wird die Größe des
Speicherbereichs verdoppelt -, damit nicht bei jedem Hinzufügen eines
Zeichens Speicher allokiert werden muss.
> Bei beliebiger Vergrößerung müsste ja quasi jedes Zeichen einen Zeiger
> auf das nächste besitzen.
Nicht bei String oder List, aber es gibt die Klasse LinkedList
(LinkedList(Of T)), bei dies so funktioniert. Der Einsatz ist aber nur
in speziellen Fällen sinnvoll. Einerseits, weil einige Operationen
deutlich weniger effizient sind, da man sich ja "durchhangeln" muss,
andererseits weil die Daten im Speicher verstreut liegen und der
CPU-Cache das nicht mag (wobei das natürlich bei Referenztypen auch bei
anderen Datenstrukturen der Fall ist).
https://msdn.microsoft.com/de-de/library/wak0wfyt.aspx
https://msdn.microsoft.com/de-de/library/w8k3cys2.aspx
https://msdn.microsoft.com/de-de/library/he2s3bh7
http://csharpindepth.com/Articles/General/Strings.aspx