Piszę interpreter języka w C, a moja string
typ zawiera atrybut length
, tak:Dlaczego łańcuchy zakończone znakiem NUL? Lub: null zakończone vs. przechowywania znaków + długość
struct String
{
char* characters;
size_t length;
};
Z tego powodu muszę wydać dużo czasu w moim tłumaczu obsługującym ten rodzaj ciągu ręcznie, ponieważ C nie zawiera wbudowanej obsługi tego. Zastanawiałem się nad przejściem na proste zakończone znakiem NUL tylko po to, aby spełnić podstawowe C, ale wydaje się, że istnieje wiele powodów, aby nie:
Sprawdzanie granic jest wbudowane, jeśli używasz "długość" zamiast szukanie zerowej wartości.
Musisz przemierzyć cały ciąg, aby znaleźć jego długość.
Musisz wykonać dodatkowe czynności, aby obsłużyć pusty znak w środku zakończonego znakiem NUL łańcucha.
Łańcuchy zakończone znakiem zakończonym znakiem NUL słabo radzą sobie z kodowaniem Unicode.
Ciągi, które nie są zakończone znakiem NULL, mogą obsługiwać więcej, tzn. Znaki "Hello, world" i "Hello" mogą być przechowywane w tym samym miejscu, tylko o różnych długościach. Nie można tego zrobić z łańcuchami zakończonymi znakiem NUL.
Wycinek łańcucha (uwaga: ciągi są niezmienne w moim języku). Oczywiście drugi jest wolniejszy (i bardziej podatny na błędy: pomyśl o dodaniu do obu funkcji sprawdzania błędów dla begin
i end
. Zastanawiam się dlaczego C ich używa:
struct String slice(struct String in, size_t begin, size_t end)
{
struct String out;
out.characters = in.characters + begin;
out.length = end - begin;
return out;
}
char* slice(char* in, size_t begin, size_t end)
{
char* out = malloc(end - begin + 1);
for(int i = 0; i < end - begin; i++)
out[i] = in[i + begin];
out[end - begin] = '\0';
return out;
}
Po tym wszystkim, moje myślenie o tym, czy nie powinno się używać ciągi zerowych jest zakończone!
Moje pytanie brzmi: czy są jakieś korzyści z zerowego rozwiązania, którego mi brakuje?
Ponieważ malloc() jest tak drogi w C, sugeruję użyć tej struktury: struct String {size_t length; char [1] characters; } Po prostu przydziel strlen (s) + 1 + sizeof (size_t) lub strlen (s) + sizeof (String) bytes i skopiuj ciąg znaków na adres i znaki. –
To proste. To jest korzyść. –