C ++에서 문자열 상수에서 'char *'로의 변환이 더 이상 사용되지 않습니다.


154

나는 수업이 있습니다 private char str[256];

그리고 그것을 위해 명시 적 생성자가 있습니다.

explicit myClass(const char *func)
{
    strcpy(str,func);
}

나는 그것을 다음과 같이 부른다.

myClass obj("example");

이것을 컴파일하면 다음 경고가 나타납니다.

문자열 상수에서 'char *'로의 더 이상 사용되지 않는 변환

왜 이런 일이 발생합니까?


1
보다 안전한 사본 strncpy(str, func, 255)대신에 사용해야 합니다 strcpy(str, func). 그리고 strncpy는 문자열 끝에 '\ 0'을 추가하는 것을 잊지 마십시오.
파트리스 베르나 솔라

2
"strncpy (str, func, sizeof (str)); str [sizeof (str)-1] = '\ 0';"
Warren Young

3
위의 내용은 당신이 인용 한 경고를 제공한다고 생각하지 않지만, 비슷한 코드는 확실합니다. 의미있는 답변을 얻으려면 경고를 생성하는 최소한의 컴파일 예제를 게시해야합니다.
sbi

3
@Patrice, Warren : strncpy를 사용하지 마십시오. strcpy의 안전한 버전은 아닙니다. strcpy_s를 사용 (또는 다시 구현)하십시오.
Steve Jessop

문제가 있는데, 일반적인 solaris 또는 ARM (target) 빌드가 아닌 -X86 빌드에 대해서만 이러한 문제를 표시하므로 이것을 무시하고 있습니다. 샘플 코드에도 정상적으로 경고가 표시되지 않아 여전히 수정 프로그램을 찾을 수 없습니다. 다들 감사 해요!
mkamthan

답변:


144

다음과 같은 상황이 발생할 때마다 표시되는 오류 메시지입니다.

char* pointer_to_nonconst = "string literal";

왜? C와 C ++는 문자열 리터럴의 유형이 다릅니다. C에서 유형은 char 배열이고 C ++에서는 상수 char 배열입니다. 어쨌든 문자열 리터럴의 문자를 변경할 수 없으므로 C ++의 const는 실제로 제한 사항이 아니라 유형 안전 문제입니다. 에서 변환 const char*하려면 char*안전을 위해 명시 적 캐스트없이 일반적으로 가능하지 않다. 그러나 C와의 이전 버전과의 호환성을 위해 C ++ 언어는 여전히 문자열 리터럴을 a에 할당 char*하고이 변환이 더 이상 사용되지 않는다는 경고를 표시합니다.

따라서 어딘가에 constconst 정확성을위한 프로그램에서 하나 이상이 누락되었습니다 . 그러나 당신이 우리에게 보여준 코드는 이런 종류의 더 이상 사용되지 않는 변환을하지 않기 때문에 문제가되지 않습니다. 경고는 다른 곳에서 나왔을 것입니다.


17
OP가 실제로 문제를 보여주는 코드를 제공하지 않았다는이 질문에 대한 견해와 투표를 고려하는 것은 불행합니다.
Shafik Yaghmour 2014 년

1
생성자 const에서 를 삭제하여 OP 코드로 문제를 재현 할 수 있습니다 MyClass. 그러면 const다시 추가하여 문제를 해결할 수 있습니다 .
Theodore Murdock

145

경고 :

문자열 상수에서 'char *'로의 더 이상 사용되지 않는 변환

당신이 게시 한 코드가 아닌 곳에서 다음과 같은 일을하기 때문에 주어집니다 :

void foo(char* str);
foo("hello");

문제는 당신이 (유형 문자열 리터럴을 변환하려고하는 것입니다 const char[]으로) char*.

배열이 포인터로 쇠약 const char[]하기 const char*때문에를 로 변환 할 수 있지만 수행중인 작업은 가변 변수를 상수로 만드는 것입니다.

이 변환은 아마도 C 호환성에 허용되며 언급 된 경고 만 제공합니다.


96

대답 없음. fnieto의 2-Fernando Nieto 는 코드의 어딘가에서 (포스트 코드가 아닌) 다음과 같은 일을하기 때문에이 경고가 명확하고 정확하게 설명되어 있습니다.

void foo(char* str);
foo("hello");

그러나 코드를 경고없이 유지하려면 코드를 각각 변경하십시오.

void foo(char* str);
foo((char *)"hello");

즉, 단순히 string상수를로 캐스팅하십시오 (char *).


17
또는 다음 함수를 작성하십시오. void foo (const char * str)
Caprooja

3
@Caprooja 네, 매개 변수를 '상수를 가리키는 포인터'로 선언하면이 경우에도 작동합니다. 그러나이 변경으로 사용자는 구현 부분에서 수행 할 수있는 'str'포인터를 사용하여 주소에 저장된 값을 더 이상 변경 / 재 할당 할 수 없습니다. 그래서 그것은 당신이 찾고 싶을 수도 있습니다.
sactiw

1
@sactiw 그대로 유지해야 할 이유 void foo(char* str)가 있습니까? 나는 우리가 어쨌든 양식 str을 할 수 없다고 생각 foo했다. 심지어 매개 변수는 비 const로 작성되었다.
kgf3JfUtW

37

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");

배열은 이미 상수 포인터이므로 포인터 대신 배열을 사용할 수도 있습니다.


7
솔루션 3의 경우가 strdup있습니다. 코드와 달리 종료 NUL 문자를위한 공간을 할당하고 할당을 초과하지 않습니다.
Ben Voigt

2
해결 방법 2는 피해야합니다.
궤도에서 가벼움 경주

실제로 솔루션 2는 C ++에서 char * x = static_cast <char *> ( "foo bar") 일 수 있습니다.
Kehe CAI

3
Anil 당신은 당신의 답변에 주석을 통합 할 것입니까? 해결 방법 3은 여전히 ​​위험합니다.
궤도에서 가벼움

@LightnessRacesinOrbit 답변을 제공해 주시겠습니까? 왜 솔루션 2와 3을 피해야하며 위험하다고 잘못했는지 이해하지 못합니다.
Gladclef

4

실제로 문자열 상수 리터럴은 const char * 또는 char *가 아니라 char []입니다. 그것은 이상하지만 c ++ 사양으로 작성되었습니다. 이를 수정하면 컴파일러가 코드 세그먼트에이를 저장할 수 있으므로 동작이 정의되지 않습니다.


5
rvalue로 수정할 수 없기 때문에 const char []라고 말하고 싶습니다.
fnieto-Fernando Nieto

3

아마도 당신은 이것을 시도 할 수 있습니다 :

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

그것은 나를 위해 작동


2

코드 시작 부분에이 매크로를 추가하여이 문제를 해결합니다. 또는에 추가하십시오 ( <iostream>hehe).

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())

8
"또는 <iostream>에 추가" 무엇?!
궤도에서 가벼움

", hehe"가 편집 된 이유가 무엇이든 (농담임을 암시 함)
Someguynamedpie

C_TEXT함수 호출 ( foo(C_TEXT("foo"));)에는 좋지만 값이 변수에 저장된 경우 정의되지 않은 동작이 필요합니다 char *x = C_TEXT("foo");.- x할당을 제외하고 사용 하는 메모리가 해제되었으므로 정의되지 않은 동작은 정의되지 않은 동작입니다.
Martin Bonner는 Monica

1

이 문제의 원인 ( char* str = "some string"다른 사람들이 설명한 문제보다 감지하기가 더 어렵습니다 )은 사용 중 constexpr입니다.

constexpr char* str = "some string";

그것은와 비슷하게 동작 할 것 const char* str같으며 char*, 전에 발생했던 것처럼 경고를 일으키지 않지만 대신으로 동작합니다 char* const str.

세부

상수 포인터 및 상수 포인터 사이의 차이 const char* str와는 char* const str다음과 같이 설명 될 수있다.

  1. const char* str: str을 const char에 대한 포인터로 선언합니다. 이것은이 포인터가 가리키는 데이터가 상수임을 의미합니다. 포인터를 수정할 수 있지만 데이터를 수정하려고하면 컴파일 오류가 발생합니다.
    1. str++ ;: 유효 합니다. 가리키는 데이터가 아니라 포인터를 수정하고 있습니다.
    2. *str = 'a';: 유효하지 않습니다 . 가리키는 데이터를 수정하려고합니다.
  2. char* const str: str을 char에 대한 const 포인터로 선언하십시오. 이는 점이 일정하지만, 지시되는 데이터도 일정하지 않음을 의미합니다. 포인터는 수정할 수 없지만 포인터를 사용하여 데이터를 수정할 수 있습니다.
    1. str++ ;: 유효하지 않습니다 . 상수 인 포인터 변수를 수정하려고합니다.
    2. *str = 'a';: 유효 합니다. 가리키는 데이터를 수정하려고합니다. 이 경우 컴파일 오류가 발생하지 않지만 런타임 오류 가 발생합니다 . 문자열은 컴파일 된 바이너리의 읽기 전용 섹션으로 이동합니다. 이 문장은 예를 들어 메모리를 동적으로 할당 한 경우에 적합합니다. char* const str = new char[5];.
  3. const char* const str: str을 const char에 대한 const 포인터로 선언합니다. 이 경우 포인터를 가리 키거나 가리키는 데이터를 수정할 수 없습니다.
    1. str++ ;: 유효하지 않습니다 . 상수 인 포인터 변수를 수정하려고합니다.
    2. *str = 'a';: 유효하지 않습니다 . 우리는이 포인터가 가리키는 데이터를 수정하려고 노력하고 있습니다.

내 경우에는 문제는 내가 아닌 constexpr char* str것처럼 작동 할 것으로 기대했다는 것이 었습니다.const char* strchar* const str 시각적으로 전자에 더 가깝게 보이기 때문에 것입니다.

또한에 대해 생성 된 경고는와 constexpr char* str = "some string"약간 다릅니다 char* str = "some string".

  1. 컴파일러 경고 constexpr char* str = "some string":ISO C++11 does not allow conversion from string literal to 'char *const'
  2. 에 대한 컴파일러 경고 char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'.

당신이 사용할 수있는 C의 횡설수설 ↔ 영어 변환 변환을 C쉽게 이해할 수있는 영어 문장을 선언하고, 그 반대의 경우도 마찬가지입니다. 이것은 C유일한 도구이므로 독점적 인 constexpr과 같은 것을 지원하지 않습니다 C++.


0

나도 같은 문제가 발생했습니다. 그리고 내가 한 간단한 일은 char * 대신 const char *를 추가하는 것입니다. 그리고 문제가 해결되었습니다. 다른 사람들이 위에서 언급했듯이 호환 가능한 오류입니다. C는 문자열을 char 배열로 취급하고 C ++는 문자열을 const char 배열로 취급합니다.


0

그 가치에 대해서는이 간단한 래퍼 클래스가 C ++ 문자열을 char *다음으로 변환하는 데 도움이된다는 것을 알았습니다 .

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};

-1

다음은 해결책을 보여줍니다. 문자열 의 상수 배열에 대한 변수 포인터에 문자열을 할당하십시오 (문자열 은 문자의 상수 배열에 대한 상수 포인터-길이 정보).

#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';
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.