나는 수업이 있습니다 private char str[256];
그리고 그것을 위해 명시 적 생성자가 있습니다.
explicit myClass(const char *func)
{
strcpy(str,func);
}
나는 그것을 다음과 같이 부른다.
myClass obj("example");
이것을 컴파일하면 다음 경고가 나타납니다.
문자열 상수에서 'char *'로의 더 이상 사용되지 않는 변환
왜 이런 일이 발생합니까?
나는 수업이 있습니다 private char str[256];
그리고 그것을 위해 명시 적 생성자가 있습니다.
explicit myClass(const char *func)
{
strcpy(str,func);
}
나는 그것을 다음과 같이 부른다.
myClass obj("example");
이것을 컴파일하면 다음 경고가 나타납니다.
문자열 상수에서 'char *'로의 더 이상 사용되지 않는 변환
왜 이런 일이 발생합니까?
답변:
다음과 같은 상황이 발생할 때마다 표시되는 오류 메시지입니다.
char* pointer_to_nonconst = "string literal";
왜? C와 C ++는 문자열 리터럴의 유형이 다릅니다. C에서 유형은 char 배열이고 C ++에서는 상수 char 배열입니다. 어쨌든 문자열 리터럴의 문자를 변경할 수 없으므로 C ++의 const는 실제로 제한 사항이 아니라 유형 안전 문제입니다. 에서 변환 const char*하려면 char*안전을 위해 명시 적 캐스트없이 일반적으로 가능하지 않다. 그러나 C와의 이전 버전과의 호환성을 위해 C ++ 언어는 여전히 문자열 리터럴을 a에 할당 char*하고이 변환이 더 이상 사용되지 않는다는 경고를 표시합니다.
따라서 어딘가에 constconst 정확성을위한 프로그램에서 하나 이상이 누락되었습니다 . 그러나 당신이 우리에게 보여준 코드는 이런 종류의 더 이상 사용되지 않는 변환을하지 않기 때문에 문제가되지 않습니다. 경고는 다른 곳에서 나왔을 것입니다.
const에서 를 삭제하여 OP 코드로 문제를 재현 할 수 있습니다 MyClass. 그러면 const다시 추가하여 문제를 해결할 수 있습니다 .
경고 :
문자열 상수에서 'char *'로의 더 이상 사용되지 않는 변환
당신이 게시 한 코드가 아닌 곳에서 다음과 같은 일을하기 때문에 주어집니다 :
void foo(char* str);
foo("hello");
문제는 당신이 (유형 문자열 리터럴을 변환하려고하는 것입니다 const char[]으로) char*.
배열이 포인터로 쇠약 const char[]하기 const char*때문에를 로 변환 할 수 있지만 수행중인 작업은 가변 변수를 상수로 만드는 것입니다.
이 변환은 아마도 C 호환성에 허용되며 언급 된 경고 만 제공합니다.
로 대답 없음. fnieto의 2-Fernando Nieto 는 코드의 어딘가에서 (포스트 코드가 아닌) 다음과 같은 일을하기 때문에이 경고가 명확하고 정확하게 설명되어 있습니다.
void foo(char* str);
foo("hello");
그러나 코드를 경고없이 유지하려면 코드를 각각 변경하십시오.
void foo(char* str);
foo((char *)"hello");
즉, 단순히 string상수를로 캐스팅하십시오 (char *).
void foo(char* str)가 있습니까? 나는 우리가 어쨌든 양식 str을 할 수 없다고 생각 foo했다. 심지어 매개 변수는 비 const로 작성되었다.
3 가지 해결책이 있습니다.
해결책 1 :
const char *x = "foo bar";
해결책 2 :
char *x = (char *)"foo bar";
해결책 3 :
char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");
배열은 이미 상수 포인터이므로 포인터 대신 배열을 사용할 수도 있습니다.
strdup있습니다. 코드와 달리 종료 NUL 문자를위한 공간을 할당하고 할당을 초과하지 않습니다.
실제로 문자열 상수 리터럴은 const char * 또는 char *가 아니라 char []입니다. 그것은 이상하지만 c ++ 사양으로 작성되었습니다. 이를 수정하면 컴파일러가 코드 세그먼트에이를 저장할 수 있으므로 동작이 정의되지 않습니다.
코드 시작 부분에이 매크로를 추가하여이 문제를 해결합니다. 또는에 추가하십시오 ( <iostream>hehe).
#define C_TEXT( text ) ((char*)std::string( text ).c_str())
C_TEXT함수 호출 ( foo(C_TEXT("foo"));)에는 좋지만 값이 변수에 저장된 경우 정의되지 않은 동작이 필요합니다 char *x = C_TEXT("foo");.- x할당을 제외하고 사용 하는 메모리가 해제되었으므로 정의되지 않은 동작은 정의되지 않은 동작입니다.
이 문제의 원인 ( char* str = "some string"다른 사람들이 설명한 문제보다 감지하기가 더 어렵습니다 )은 사용 중 constexpr입니다.
constexpr char* str = "some string";
그것은와 비슷하게 동작 할 것 const char* str같으며 char*, 전에 발생했던 것처럼 경고를 일으키지 않지만 대신으로 동작합니다 char* const str.
상수 포인터 및 상수 포인터 사이의 차이 const char* str와는 char* const str다음과 같이 설명 될 수있다.
const char* str: str을 const char에 대한 포인터로 선언합니다. 이것은이 포인터가 가리키는 데이터가 상수임을 의미합니다. 포인터를 수정할 수 있지만 데이터를 수정하려고하면 컴파일 오류가 발생합니다.
str++ ;: 유효 합니다. 가리키는 데이터가 아니라 포인터를 수정하고 있습니다.*str = 'a';: 유효하지 않습니다 . 가리키는 데이터를 수정하려고합니다.char* const str: str을 char에 대한 const 포인터로 선언하십시오. 이는 점이 일정하지만, 지시되는 데이터도 일정하지 않음을 의미합니다. 포인터는 수정할 수 없지만 포인터를 사용하여 데이터를 수정할 수 있습니다.
str++ ;: 유효하지 않습니다 . 상수 인 포인터 변수를 수정하려고합니다.*str = 'a';: 유효 합니다. 가리키는 데이터를 수정하려고합니다. 이 경우 컴파일 오류가 발생하지 않지만 런타임 오류 가 발생합니다 . 문자열은 컴파일 된 바이너리의 읽기 전용 섹션으로 이동합니다. 이 문장은 예를 들어 메모리를 동적으로 할당 한 경우에 적합합니다. char* const str = new char[5];.const char* const str: str을 const char에 대한 const 포인터로 선언합니다. 이 경우 포인터를 가리 키거나 가리키는 데이터를 수정할 수 없습니다.
str++ ;: 유효하지 않습니다 . 상수 인 포인터 변수를 수정하려고합니다.*str = 'a';: 유효하지 않습니다 . 우리는이 포인터가 가리키는 데이터를 수정하려고 노력하고 있습니다.내 경우에는 문제는 내가 아닌 constexpr char* str것처럼 작동 할 것으로 기대했다는 것이 었습니다.const char* strchar* const str 시각적으로 전자에 더 가깝게 보이기 때문에 것입니다.
또한에 대해 생성 된 경고는와 constexpr char* str = "some string"약간 다릅니다 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 *'.당신이 사용할 수있는 C의 횡설수설 ↔ 영어 변환 변환을 C쉽게 이해할 수있는 영어 문장을 선언하고, 그 반대의 경우도 마찬가지입니다. 이것은 C유일한 도구이므로 독점적 인 constexpr과 같은 것을 지원하지 않습니다 C++.
그 가치에 대해서는이 간단한 래퍼 클래스가 C ++ 문자열을 char *다음으로 변환하는 데 도움이된다는 것을 알았습니다 .
class StringWrapper {
std::vector<char> vec;
public:
StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
}
char *getChars() {
return &vec[0];
}
};
다음은 해결책을 보여줍니다. 문자열 의 상수 배열에 대한 변수 포인터에 문자열을 할당하십시오 (문자열 은 문자의 상수 배열에 대한 상수 포인터-길이 정보).
#include <iostream>
void Swap(const char * & left, const char * & right) {
const char *const temp = left;
left = right;
right = temp;
}
int main() {
const char * x = "Hello"; // These works because you are making a variable
const char * y = "World"; // pointer to a constant string
std::cout << "x = " << x << ", y = " << y << '\n';
Swap(x, y);
std::cout << "x = " << x << ", y = " << y << '\n';
}
strncpy(str, func, 255)대신에 사용해야 합니다strcpy(str, func). 그리고 strncpy는 문자열 끝에 '\ 0'을 추가하는 것을 잊지 마십시오.