W C prototypem funkcji wartości bezwzględnej (która akceptuje liczbę zmiennoprzecinkową) jest
float fabsf( float );
Dlaczego ten prototyp nie przyjmuje stałej wartości, takiej jak ta:
float fabsf( float const );
fabsf nie zmieni wartości danych wejściowych, prawda?
Jeśli mam funkcję, która akceptuje dane wejściowe i wywołuje fabsf, czy jestem zmuszony unikać podawania danych wejściowych jako const?
Jaki jest właściwy sposób postępowania z poprawnością const w tej sytuacji?
c
function
const
pass-by-value
użytkownik24205
źródło
źródło
const
jest tu zbędny, jak myślisz, co się dzieje?const
jest całkowicie bez znaczenia.float const x = -1.0; float y = fabsf(x);
więc wydaje mi się, żefabsf
nie akceptują wejść const. Nie można powiedzieć „możesz przekazać mifloat
wartość, ale nie możeszconst float
”. (I jak widzimy w odpowiedziach, C nie zapewnia sposobu na wymaganie, aby dane wejściowe do funkcji były afloat const
.)Odpowiedzi:
Edytować
Jak skomentował MM, o parametrach prototypów
const
jest ignorowany. Edytowane źródło oryginalnej odpowiedzi (patrz poniżej) pokazuje to:Brak komunikatu o błędzie.
W każdym razie zostawię oryginał na miejscu w nadziei, że może to pomóc.
Oryginalny
const
Na parametr sprawia, że ten parametr tylko do odczytu wewnątrz funkcji.Na przykład:
To źródło nie skompiluje się bez komunikatu o błędzie.
Funkcja
correct()
odczyta podaną wartość, zmieni jej znak i zwróci wartość zanegowaną.Funkcja
erroneous()
wydaje się działać tak samo, z tym wyjątkiem, że do parametru przypisano przypisanie. Ale jako parametr jestconst
to niedozwolone.Następnie funkcja
changer()
będzie działać tak samo jak poprzednio, ale nie spowoduje błędów.Spójrzmy na stronę połączeń:
Zmienna
f
podana jako argument zostanie skopiowana do parametruvalue
. Nigdy się nie zmieni, nawet jeślichanger()
zostanie wywołany.Możesz spojrzeć na parametry jako na rodzaj zmiennych lokalnych. W rzeczywistości są one w większości obsługiwane w ten sposób w wygenerowanym kodzie maszynowym.
Dlaczego więc
const
czasami widzisz ? Widzisz to, jeśli wskaźnik jest zdefiniowany jako parametr.Jeśli nie chcesz, aby wskazywana wartość była zmieniana, musisz dodać
const
; ale zrób to we właściwej pozycji!źródło
float fabsf( float const );
nie ma nic wspólnego z implementacją funkcji (która nie musi się powtarzaćconst
), w rzeczywistościconst
jest całkowicie ignorowany w prototypieC używa parametru pass by value. Wartość parametru funkcji jest kopią podanego argumentu.
Można kopiować zarówno zmiennoprzecinkowe const, jak i non-const, a wynikiem jest zmiennoprzecinkowe non-const.
Jest podobny do przypisania:
W rzeczywistości język określa, że wartość wyrażenia nigdy nie może być
const
, tzn. Gdy wartość jest odczytywana ze zmiennej, nie jest to wartość,const
nawet jeśli zmienna była.źródło
Ponieważ język C używa semantyki przekazywania według wartości, każdy przekazany do niego argument, chociaż można go zmodyfikować wewnętrznie, nie wpływa bezpośrednio na przekazywaną wartość.
Oznacza to, że z punktu widzenia rozmówcy,
float fabsf( float );
ifloat fabsf( const float );
są takie same. Więc nie ma sensu tworzyć parametruconst
.Gdzie to ma sens stosowania
const
jest jeśli parametr przekazać w to wskaźnik, na przykład:Ta funkcja, pomimo tego, co sugeruje nazwa, może wyłuskać dany wskaźnik i modyfikować to, co wskazuje, tj.
str[0] = 'x'
Aby spowodować zmianę widoczną przez funkcję wywołującą. Jeśli tę funkcję zdefiniowano w następujący sposób:Dzwoniący ma zapewnioną, że funkcja nie może dokonywać żadnych modyfikacji tego, co
str
wskazuje.źródło
((char*)str)[0] = 'f'
.const ... *
Na liście argumentów jest więc tylko „oświadczenie woli”.Aby dodać perspektywę prawnika językowego:
Oznacza to, że te dwa są kompatybilne:
Dlatego możesz napisać prototyp z lub bez
const
(co oznacza, że nie ma większego sensu; mniej pisać / czytać) i możesz dodaćconst
definicję funkcji, jeśli chcesz uniknąć przypadkowej modyfikacji parametru (skopiowane - wywołaj przez wartość!) Wewnątrz funkcji ciało.źródło