C에서 문자열 리터럴의 "수명"
다음 함수에 의해 반환 된 포인터에 액세스 할 수 없습니까?
char *foo( int rc )
{
switch (rc)
{
case 1: return("one");
case 2: return("two");
default: return("whatever");
}
}
따라서 C / C ++에서 지역 변수의 수명은 실제로 함수 내에서만 가능합니다. 즉, char* foo(int)
종료 후 반환되는 포인터는 더 이상 아무 의미도 없습니다.
나는 지역 var의 수명에 대해 약간 혼란 스럽습니다. 누구든지 나에게 좋은 설명을 줄 수 있습니까?
예, 지역 변수의 수명 은 생성 된 범위 ( {
, }
) 내에 있습니다.
로컬 변수에는 자동 또는 로컬 저장소가 있습니다.
자동은 그들이 자동으로이 끝을 생성하는 내 범위를 한 번 파괴하기 때문이다.
그러나 여기에있는 것은 구현 정의 읽기 전용 메모리에 할당되는 문자열 리터럴입니다. 문자열 리터럴은 지역 변수와 다르며 프로그램 수명 내내 살아 있습니다. 정적 기간 [참조 1] 수명이 있습니다.
주의 사항!
그러나 문자열 리터럴의 내용을 수정하려는 시도는 정의되지 않은 동작입니다. 사용자 프로그램은 문자열 리터럴의 내용을 수정할 수 없습니다.
따라서 항상 const
문자열 리터럴을 선언하는 동안 사용하는 것이 좋습니다 .
const char*p = "string";
대신에,
char*p = "string";
사실, C ++ const
에서는 c 에는 없지만 문자열 리터럴을 선언하는 것은 더 이상 사용되지 않습니다 . 그러나 문자열 리터럴을 a로 선언하면 const
두 번째 경우에 문자열 리터럴을 수정하려고 할 때 컴파일러가 일반적으로 경고를 표시하는 이점이 있습니다.
샘플 프로그램 :
#include<string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[]="Sample string";
strcpy(str1,source); //No warning or error just Uundefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
산출:
cc1 : 경고가 오류로 처리됨
prog.c : 함수 'main'에서 :
prog.c : 9 : 오류 : 'strcpy'의 인수 1을 전달하면 포인터 대상 유형에서 한정자가 삭제됩니다.
컴파일러는 두 번째 경우에 대해 경고하지만 첫 번째 경우에는 경고하지 않습니다.
편집 : 여기에 몇 명의 사용자가 묻는 질문에 대답하려면 :
정수 리터럴은 무엇입니까?
즉,이 코드는 유효합니다.
int *foo()
{
return &(2);
}
대답은 아니오입니다.이 코드는 유효하지 않으며 형식이 잘못되어 컴파일러 오류가 발생합니다.
다음과 같은 것 :
prog.c:3: error: lvalue required as unary ‘&’ operand
문자열 리터럴은 l- 값입니다. 즉 : 문자열 리터럴의 주소를 사용할 수 있지만 내용을 변경할 수는 없습니다.
그러나, 다른 리터럴 ( int
, float
, char
등) (이 용어는 사용 된 c 표준 R-값인 식의 값 이 대한) 자신의 어드레스가 전혀 취할 수는 없다.
[참조 1] C99 표준 6.4.5 / 5 "문자열 리터럴-의미 체계":
In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence; for wide string literals, the array elements have type wchar_t, and are initialized with the sequence of wide characters...
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
It's valid, string literals have static storage duration, so the pointer is not dangling.
For C, that is mandated in section 6.4.5, paragraph 6:
In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.
And for C++ in section 2.14.5, paragraphs 8-11:
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n
const char
”, where n is the size of the string as defined below, and has static storage duration (3.7).9 A string literal that begins with u, such as
u"asdf"
, is achar16_t
string literal. Achar16_t
string literal has type “array of nconst char16_t
”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters. A single c-char may produce more than onechar16_t
character in the form of surrogate pairs.10 A string literal that begins with U, such as
U"asdf"
, is achar32_t
string literal. Achar32_t
string literal has type “array of nconst char32_t
”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.11 A string literal that begins with L, such as
L"asdf"
, is a wide string literal. A wide string literal has type “array of nconst wchar_t
”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.
String literals are valid for the whole program (and are not allocated not the stack), so it will be valid.
Also, string literals are read-only, so (for good style) maybe you should change foo
to const char *foo(int)
Yes, it is valid code, case 1 below. You can safely return C strings from a function in at least these ways:
const char*
to a string literal. Can't be modified, must not be freed by caller. Rarely useful for the purpose of returning a default value, because of the freeing problem described below. Might make sense if you actually need to pass a function pointer somewhere, so you need a function returning a string..char*
orconst char*
to static char buffer. Must not be freed by caller. Can be modified (either by caller if not const, or by the function returning it), but a function returning this can't (easily) have multiple buffers, so not (easily) thread safe, and caller may need to copy the returned value before calling the function again.char*
to a buffer allocated withmalloc
. Can be modified, but must usually be explicitly freed by caller, and has the heap allocation overhead.strdup
is of this type.const char*
orchar*
to a buffer, which was passed as an argument to the function (returned pointer does not need to point to the first element of argument buffer). Leaves responsibility of buffer/memory management to caller. Many standard string functions are of this type.
One problem is, mixing these in one function can get complicated. Caller needs to know how it should handle the returned pointer, how long it is valid, and if caller should free it, and there's no (nice) way of determining that at runtime. So you can't for example have a function, which sometimes returns a pointer to a heap-allocated buffer which caller needs to free
, and sometimes a pointer to a default value from string literal, which caller must not free
.
Good question. In general, you would be right, but your example is the exception. The compiler statically allocates global memory for a string literal. Therefore, the address returned by your function is valid.
That this is so is a rather convenient feature of C, isn't it? It allows a function to return a precomposed message without forcing the programmer to worry about the memory in which the message is stored.
See also @asaelr's correct observation re const
.
Local variables are only valid within the scope they're declared, however you don't declare any local variables in that function.
It's perfectly valid to return a pointer to a string literal from a function, as a string literal exists throughout the entire execution of the program, just as a static
or a global variable would.
If you're worrying about what you're doing might be invalid undefined, you should turn up your compiler warnings to see if there is in fact anything you're doing wrong.
str will never be dangling pointer. Because it points to static address
where string literals resides . It will be mostly readonly
and global
to the program when it will be loaded . Even if you try to free or modify ,it will throw segmentation fault
on platforms with memory protection .
A local variable is allocated on the stack. After the function finishes, the variable goes out of scope and is no longer accessible in the code. However, if you have a global (or simply - not yet out of scope) pointer that you assigned to point to that variable, it will point to the place in the stack where that variable was. It could be a value used by another function, or a meaningless value.
In the above example shown by you, you are actually returning the allocated pointers to whatever function that calls the above. So It would not become a local pointer. And moreover the pointers that are needed to be returned, memory is allocated in global segment.
Thanking You,
Viharri P L V.
참고URL : https://stackoverflow.com/questions/9970295/life-time-of-string-literal-in-c
'developer tip' 카테고리의 다른 글
탐색 컨트롤러 내부의 탭 모음 컨트롤러 또는 탐색 루트보기 공유 (0) | 2020.10.10 |
---|---|
Python을 사용하여 파일에 예쁜 인쇄 JSON 데이터 (0) | 2020.10.09 |
SKScene에서 버튼 설정 (0) | 2020.10.09 |
Android에서 JSON 배열 (Json 개체 아님)을 구문 분석하는 방법 (0) | 2020.10.09 |
OSX El Capitan에서 setuptools 업그레이드 (0) | 2020.10.09 |