Zwracanie wskażnika do argumentu (const)

0

Witam,

Chcę napisać własną implementację funkcji strstr. Chcę zachować takie same typy argumenów i wartości zwracanej. Jak dotąd utknąłem na samym początku, z prostej przyczyny.

 char *strstr(const char *s1, const char *s2) {
    if (!*s2) {
        return s1;
    }
}

Koduję w Clion i od razy krzyczy mi, że robię źle, gdyż argument jest stałą, a ja zwracam wskażnik do niego, co łamie zasadę "stałości". Oczywiście mogę to rzutować:

char *strstr(const char *s1, const char *s2) {
    if (!*s2) {
        return (char *) s1;
    }
} 

I teraz pytanie. Co jest lepsze z punktu widzenia dobrych praktyk, co jest bardziej "profesjonalne" i milej widziane. Nie wiem do końca, czy rozumieć, że const jest tylko w obrębie funkcji, a co potem zrobię poza funkcją to moja sprawa, czy słowo kluczowe const przy argumencie zobowiązuje mnie także do pewnych przedsięwzięć poza nią. Oczywiście oba sposoby działają (u mnie ;)). Może jest to zależne od kompilatora?

3

Zwracaj char const*, zamiast zdradziecko zwracać błędny typ.

char * str = strstr("blah","a");
str[0] = 'b'; // UB, crash

Dzięki const castowi w powyższym uniemożliwiłeś wychwycenie błędu w czasie kompilacji.

0

Oczywiście można tak zrobić. Pytanie dlaczego funkcja z biblioteki nie zwraca consta tylko ma taką implementację jak napisałem powyżej?

0

Bo prototypy funkcji z biblioteki standardowej pamiętają lata 80-te, gdy const nie istniało w języku.

0

Gdyby to było C++ to bym powiedział, że w strstr albo masz i argumenty i typ zwracany const, albo żadne z nich, no i że odrzucanie const w C++ to grzech.
No ale to jest C, gdzie const niby już jest, ale potraktowane po macoszemu, a strstr - staaara funkcja - istniała kiedyś w wersji char* strstr(char*, char*), zanim przyszło const, a teraz istnieje w takiej jak napisałeś - przyjmujące argumenty jako const i zwracające wskaźnik bez const...
Mój zmysł estetyczny podpowiada, że takie odrzucanie brzydkie, ale wyjścia nie masz, musisz rzutować. To znaczy - nie masz, jeśli chcesz się trzymać typu z biblioteki standardowej.

Odpowiedzialność jest tutaj - jak zwykle w C i C++ - po stronie programisty. Jeśli zrobisz coś głupiego jak poniżej, to już Twoja wina:

char* c = strstr("abecadlo", "cad");
c[0] = 'r'; // ups!

1 użytkowników online, w tym zalogowanych: 0, gości: 1