Mam klasę z rozszerzeniem private char str[256];
i do tego mam jawnego konstruktora:
explicit myClass(const char *func)
{
strcpy(str,func);
}
Nazywam to tak:
myClass obj("example");
Kiedy to kompiluję, otrzymuję następujące ostrzeżenie:
przestarzała konwersja ze stałej łańcuchowej na „char *”
Dlaczego to się dzieje?
c++
string
explicit-constructor
mkamthan
źródło
źródło
strncpy(str, func, 255)
zamiast,strcpy(str, func)
aby uzyskać bezpieczniejszą kopię. A potem nie zapomnij dodać „\ 0” na końcu ciągu, ponieważ strncpy go nie dodaje.Odpowiedzi:
To jest komunikat o błędzie, który pojawia się w przypadku wystąpienia takiej sytuacji:
Czemu? Cóż, C i C ++ różnią się typem literału ciągu. W C jest to tablica znaków, aw C ++ stała tablica znaków. W każdym razie nie możesz zmieniać znaków literału ciągu, więc stała w C ++ nie jest tak naprawdę ograniczeniem, ale raczej kwestią bezpieczeństwa typu. Konwersja z
const char*
na niechar*
jest generalnie możliwa bez wyraźnej obsady ze względów bezpieczeństwa. Jednak w celu zapewnienia zgodności wstecznej z C język C ++ nadal umożliwia przypisywanie literału ciągu znaków do achar*
i wyświetla ostrzeżenie o tym, że ta konwersja jest przestarzała.Więc gdzieś brakuje jednego lub więcej
const
w swoim programie dla stałej poprawności. Ale kod, który nam pokazałeś, nie stanowi problemu, ponieważ nie wykonuje tego rodzaju przestarzałej konwersji. Ostrzeżenie musiało nadejść z innego miejsca.źródło
const
zMyClass
konstruktora ... następnie możesz go naprawić, dodając odwrotnąconst
stronę.Ostrzeżenie:
jest podawana, ponieważ gdzieś robisz (nie w opublikowanym kodzie) coś takiego:
Problem polega na tym, że próbujesz przekonwertować literał ciągu (z typem
const char[]
) nachar*
.Możesz przekonwertować a
const char[]
na,const char*
ponieważ tablica rozpada się na wskaźnik, ale to, co robisz, polega na przekształcaniu zmiennej w stałą.Ta konwersja jest prawdopodobnie dozwolona dla zgodności z C i daje tylko wspomniane ostrzeżenie.
źródło
Jako odpowiedź nie. 2 autorstwa fnieto - Fernando Nieto jasno i poprawnie opisuje, że to ostrzeżenie jest wyświetlane, ponieważ gdzieś w kodzie, który robisz (nie w kodzie, który opublikowałeś) coś takiego:
Jeśli jednak chcesz, aby Twój kod był również wolny od ostrzeżeń, po prostu wprowadź odpowiednią zmianę w kodzie:
Oznacza to, że po prostu rzuć
string
stałą na(char *)
.źródło
void foo(char* str)
to, co jest? Myślałem, że nie możemy moditystr
wfoo
każdym razie, nawet parametr jest zapisywany jako const.Istnieją 3 rozwiązania:
Rozwiązanie 1:
Rozwiązanie 2:
Rozwiązanie 3:
Tablice mogą być również używane zamiast wskaźników, ponieważ tablica jest już stałym wskaźnikiem.
źródło
strdup
. W przeciwieństwie do twojego kodu, przydzieli miejsce na kończący znak NUL i nie przekroczy alokacji.W rzeczywistości ciąg znaków nie jest ani const char * ani char *, ale char []. Jest to dość dziwne, ale zostało zapisane w specyfikacji c ++; Jeśli go zmodyfikujesz, zachowanie jest niezdefiniowane, ponieważ kompilator może przechowywać je w segmencie kodu.
źródło
Może możesz spróbować tego:
Mi to pasuje
źródło
Rozwiązuję ten problem dodając to makro gdzieś na początku kodu. Albo dodaj
<iostream>
, hehe.źródło
C_TEXT
jest w porządku dla wywołania funkcji (foo(C_TEXT("foo"));
), ale woła o niezdefiniowane zachowanie, jeśli wartość jest przechowywana w zmiennej, jakchar *x = C_TEXT("foo");
- każde użyciex
(poza przypisaniem) jest niezdefiniowanym zachowaniem, ponieważ pamięć, na którą wskazuje, została zwolniona.Przyczyną tego problemu (który jest jeszcze trudniejszy do wykrycia niż problem
char* str = "some string"
- który inni wyjaśniali) jest używanieconstexpr
.Wygląda na to, że zachowywałby się podobnie
const char* str
, a więc nie powodowałby ostrzeżenia, jak to miało miejsce wcześniejchar*
, ale zamiast tego zachowuje się jakchar* const str
.Detale
Stały wskaźnik i wskaźnik do stałej. Różnicę między
const char* str
ichar* const str
można wyjaśnić w następujący sposób.const char* str
: Zadeklaruj str jako wskaźnik do znaku stałego. Oznacza to, że dane, na które wskazuje ten wskaźnik, są stałe. Wskaźnik można modyfikować, ale każda próba modyfikacji danych spowodowałaby błąd kompilacji.str++ ;
: WAŻNY . Modyfikujemy wskaźnik, a nie wskazywane dane.*str = 'a';
: INVALID . Staramy się modyfikować wskazywane dane.char* const str
: Zadeklaruj str jako stały wskaźnik do znaku. Oznacza to, że punkt jest teraz stały, ale wskazywane dane również nie. Wskaźnik nie może być modyfikowany, ale możemy modyfikować dane za pomocą wskaźnika.str++ ;
: INVALID . Próbujemy zmodyfikować zmienną wskaźnika, która jest stałą.*str = 'a';
: WAŻNY . Staramy się modyfikować wskazywane dane. W naszym przypadku nie spowoduje to błędu kompilacji, ale spowoduje błąd wykonania , ponieważ łańcuch najprawdopodobniej trafi do sekcji tylko do odczytu skompilowanego pliku binarnego. To stwierdzenie miałoby sens, gdybyśmy mieli dynamicznie alokowaną pamięć, np.char* const str = new char[5];
.const char* const str
: Zadeklaruj str jako stały wskaźnik do stałego znaku. W tym przypadku nie możemy ani zmienić wskaźnika, ani wskazanych danych.str++ ;
: INVALID . Próbujemy zmodyfikować zmienną wskaźnika, która jest stałą.*str = 'a';
: INVALID . Próbujemy zmodyfikować dane wskazywane przez ten wskaźnik, który również jest stały.W moim przypadku chodziło o to, że spodziewałem
constexpr char* str
się zachowywać się jakconst char* str
, a niechar* const str
, ponieważ wizualnie wydaje się bliższy temu pierwszemu.Ponadto ostrzeżenie wygenerowane dla
constexpr char* str = "some string"
jest nieco inne niżchar* str = "some string"
.constexpr char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *const'
char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *'
.Wskazówka
Możesz użyć konwertera C bełkot ↔ angielski, aby przekonwertować
C
deklaracje na łatwo zrozumiałe angielskie instrukcje i odwrotnie. Jest toC
jedyne narzędzie i dlatego nie obsługuje rzeczy (takich jak constexpr), które są wyłączne dlaC++
.źródło
Ja też mam ten sam problem. Po prostu dodałem const char * zamiast char *. I problem został rozwiązany. Jak wspomnieli inni powyżej, jest to kompatybilny błąd. C traktuje łańcuchy jako tablice typu char, podczas gdy C ++ traktuje je jako tablice typu const char.
źródło
Ze względu na swoją wartość uważam, że ta prosta klasa opakowująca jest pomocna przy konwertowaniu ciągów C ++ na
char *
:źródło
Poniższy przykład ilustruje rozwiązanie, przypisz swój ciąg do wskaźnika zmiennej do stałej tablicy znaków (ciąg jest stałym wskaźnikiem do stałej tablicy znaków - plus informacje o długości):
źródło