Niejednoznaczność zaczyna się od samego standardu C. Zarówno C99, jak i C11 mają identyczny opis snprintf
funkcji. Oto opis z C99:
7.19.6.5 snprintf
Funkcja
Streszczenie
1 #include <stdio.h>
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
Opis
2 snprintf
Funkcja jest równoważna fprintf
, z tym wyjątkiem, że dane wyjściowe są zapisywane w tablicy (określonej przez argument s
), a nie w strumieniu. Jeśli n
wynosi zero, nic nie jest zapisywane i s
może być pustym wskaźnikiem. W przeciwnym razie znaki wyjściowe poza n-1
st są odrzucane, a nie zapisywane w tablicy, a znak null jest zapisywany na końcu znaków faktycznie zapisanych w tablicy. Jeśli kopiowanie odbywa się między nakładającymi się obiektami, zachowanie jest niezdefiniowane.
Zwraca
3 snprintf
Funkcja zwraca liczbę znaków, które zostałyby zapisanen
były wystarczająco duże, nie licząc kończącego znaku null lub wartości ujemnej, jeśli wystąpił błąd kodowania. W związku z tym dane wyjściowe zakończone znakiem null zostały całkowicie zapisane wtedy i tylko wtedy, gdy zwrócona wartość jest nieujemna i mniejsza niż n
.
Z jednej strony zdanie
W przeciwnym razie znaki wyjściowe poza n-1
st są odrzucane, a nie zapisywane w tablicy, a znak null jest zapisywany na końcu znaków faktycznie zapisanych w tablicy
mówi, że
jeśli ( s
wskazuje na tablicę składającą się z 3 znaków i) n
wynosi 3, to zostaną zapisane 2 znaki, a znaki poza drugim są odrzucane ; wtedy znak null jest zapisywany po tych 2 (a znak null będzie trzecim zapisanym znakiem) .
I to, jak sądzę, odpowiada na pierwotne pytanie.
ODPOWIEDŹ:
Jeśli kopiowanie odbywa się między nakładającymi się obiektami, zachowanie jest niezdefiniowane.
Jeśli n
wynosi 0, nic nie jest zapisywane na wyjściu, w
przeciwnym razie, jeśli nie napotkano błędów kodowania, wyjście jest ZAWSZE zakończone znakiem null ( niezależnie od tego, czy dane wyjściowe mieszczą się w tablicy wyjściowej, czy nie ; jeśli nie, to niektóre znaki są odrzucane, tak że wynik tablica nigdy nie jest przepełniona), w
przeciwnym razie (jeśli wystąpią błędy kodowania) dane wyjściowe mogą pozostać niezerowe .
Z drugiej strony
Ostatnie zdanie
Zatem wyjście zakończone znakiem null zostało całkowicie zapisane wtedy i tylko wtedy, gdy zwrócona wartość jest nieujemna i mniejsza niż n
daje niejednoznaczność (lub mój angielski nie jest wystarczająco dobry). Mogę zinterpretować to zdanie na co najmniej dwa sposoby:
1. Wyjście jest zakończone wartością zerową wtedy i tylko wtedy, gdy zwrócona wartość jest nieujemna i mniejsza niżn
(co oznacza, że jeśli zwrócona wartość jest nie mniejsza niż n
, tj. Dane wyjściowe (w tym kończący znak null) nie mieści się w tablicy, wtedy dane wyjściowe nie są zakończone znakiem null ).
2. Dane wyjściowe są kompletne (żadne znaki nie zostały odrzucone) wtedy i tylko wtedy, gdy zwrócona wartość jest nieujemna i mniejsza niżn
.
Uważam, że powyższa interpretacja 1 jest sprzeczna z ODPOWIEDZI, powoduje nieporozumienia i długie dyskusje. Dlatego ostatnie zdanie opisujące snprintf
funkcję wymaga zmiany w celu usunięcia wszelkich niejasności (co daje podstawy do napisania Propozycji na Standard języka C).
Uważam, że przykład niejednoznacznego sformułowania można znaleźć na stronie http://en.cppreference.com/w/c/io/fprintf (zobacz 4)
), dzięki @ "Martin Ba" za link.
Zobacz także pytanie „ snprintf: Czy są jakieś propozycje / plany C Standardu zmiany opisu tej funkcji? ”.