2016-04-13 21 views
10

strstr jest funkcją C99-zgodny, którego podpis typu jest następująca:Jak zaimplementować strstr() bez odlewania const?

char *strstr(const char *haystack, const char *needle); 

Czy możliwe jest wdrożyć tę funkcję bez rzucania away const gdzieś?

Dla odniesienia, tutaj jest Apple's implementation, a tutaj jest GNU's implementation. Obaj odrzucają na końcu const.

+0

Nie musisz niczego modyfikować (?) – sircodesalot

+2

@sircodesalot Jak właściwie * zapisujesz * funkcję bez odrzucania 'const' w celu zwrócenia wskaźnika? – Ana

+0

Zgadzam się z tobą. Typem zwracanym powinno być 'const char *'. – user3386109

Odpowiedz

9

Nie można wdrożyć strstr() bez naruszania w jakikolwiek sposób poprawności const. Gips to najprostszy sposób na zrobienie tego. Prawdopodobnie możesz jakoś ukryć naruszenie (na przykład możesz użyć wartości memcpy(), aby skopiować wartość wskaźnika), ale nie ma sensu tego robić.

Problemem jest to, że strstr() zajmuje const char* wskazujący na sznurku i zwraca niebędącą constchar* wskazujący do tego samego łańcucha.

Na przykład, program:

#include <stdio.h> 
#include <string.h> 
int main(void) { 
    const char s[] = "hello"; 
    char *result = strstr(s, "hello"); 
    *result = 'H'; 
    puts(result); 
} 

modyfikuje (lub przynajmniej próbuje modyfikować) ą const -qualified obiektów bez stosowania gips lub inny wskaźnik oczywiście niebezpieczne konstrukcję.

Powrót w 1989 roku, komitet ANSI C mógłby uniknąć tego problemu poprzez zdefiniowanie dwie różne funkcje, np:

const char *strcstr(const char *haystack, const char *needle); 
     char *strstr (  char *haystack, const char *needle); 

jedną, która zwraca wskaźnik do const char otrzymał const argumenty, a inny, że zwraca wskaźnik do modyfikowalnego char ze względu na modyfikowalny argument. (C++, który dziedziczy bibliotekę standardową C, robi to przez przeciążanie.)

strstr() to jedna z kilku standardowych funkcji napisów, które mają ten problem.

+0

Podstawowy problem polega na tym, że 'strstr' poprzedza pojęcie' const' w języku C ... –

+0

@Chris Dodd: Nawet gdyby nie, powiedziałbym, że obecny interfejs byłby bardziej odpowiedni w C niż powyższe z dwiema funkcjami. – AnT

+0

@AnT: W jaki sposób interfejs, który pozwala ci po cichu naruszać prawidłowość 'const', jest bardziej odpowiedni? –

0

Co widzisz w przypadku strstr (i niektórych innych standardowych funkcji) jest idiomatyczne rozwiązanie, którego celem jest wspieranie innych niż operacje na modyfikujące zarówno const i non-const ciągi z pojedynczego funkcji.

Tak, w celu realizacji takiej funkcji konieczne jest wyraźne odrzucenie constness ze wskaźnika wejściowego. Zauważ, że sam rzut nie narusza fizycznie niczego (co oznacza, że ​​nie próbuje modyfikować stałych danych i nie powoduje niezdefiniowanego zachowania). Otwiera to jednak drogę do takich naruszeń, zwracając niezwiązany wskaźnik do danych stałych do osoby wywołującej, tj. Narusza zasady pojęciowe dotyczące stałości.

Alternatywnym rozwiązaniem byłoby zapewnienie dwóch wersji tej samej standardowej funkcji - stałej i niestałej - ale bez przeciążania funkcji stylu C++ wymagałoby to dwóch charakterystycznych nazw funkcji, które niekoniecznie muszą wyglądać bardzo dobry pomysł (nawet z przeciążaniem funkcji w stylu C++ ma również swoje problemy).

W takim przypadku faktycznie obowiązkiem osoby dzwoniącej jest otrzymanie wyniku w formie wskaźnika tego samego typu, który został przekazany jako argument.Jeśli wskaźnik argumentu był const-kwalifikowany, bardzo dobrą praktyką programistyczną jest otrzymanie wyniku do wskaźnika, który jest także const-kwalifikowany. Dopóki przestrzegane są te wytyczne, ten idiom rzeczywiście czuje się dobrze w domu w języku C.

+0

C++ w rzeczywistości wymaga przeciążenia const dla strstr i przyjaciół, patrz sect. 21.8. Jakie problemy z tym widzisz? – rici