함수에서 char *와 char []를 반환하는 것의 차이점은 무엇입니까?
이 질문에 이미 답변이 있습니다.
첫 번째 함수는 "Hello, World"문자열을 반환하지만 두 번째 함수는 아무것도 반환하지 않는 이유입니다. 범위를 벗어난 데이터를 반환하기 때문에 두 함수의 반환 값이 정의되지 않을 것이라고 생각했습니다.
#include <stdio.h>
// This successfully returns "Hello, World"
char* function1()
{
char* string = "Hello, World!";
return string;
}
// This returns nothing
char* function2()
{
char string[] = "Hello, World!";
return string;
}
int main()
{
char* foo1 = function1();
printf("%s\n", foo1); // Prints "Hello, World"
printf("------------\n");
char* foo2 = function2(); // Prints nothing
printf("%s\n", foo2);
return 0;
}
두 번째 함수는 아무것도 반환하지 않습니다.
string
두 번째 함수 의 배열 :
char string[] = "Hello, World!";
보유 자동 저장 지속 시간 . 제어 흐름이 함수에서 반환 된 후에는 존재하지 않습니다.
반면 string
제 함수 :
char* string = "Hello, World!";
정적 저장 기간 이있는 리터럴 문자열을 가리 킵니다 . 이는 함수에서 돌아온 후에도 문자열이 여전히 존재 함을 의미합니다. 함수에서 반환하는 것은이 리터럴 문자열에 대한 포인터입니다.
문자열에 대해 배워야 할 첫 번째 사항은 문자열 리터럴이 실제로 전체 프로그램의 수명을 가진 읽기 전용 문자의 배열이라는 것입니다. 즉, 범위를 벗어나지 않으며 프로그램 실행 내내 항상 존재합니다.
첫 번째 함수 ( function1
)는 이러한 배열의 첫 번째 요소에 대한 포인터를 반환합니다.
두 번째 기능 ( function2
)은 상황이 조금 다릅니다. 여기서 변수 string
는 함수 내의 지역 변수 입니다. 따라서 범위를 벗어나 함수가 반환되면 존재하지 않게됩니다. 이 함수를 사용하면 해당 배열의 첫 번째 요소에 대한 포인터를 반환하지만 더 이상 존재하지 않는 항목을 가리 키므로 해당 포인터는 즉시 무효화됩니다. 참조를 해제하면 (전달할 때 발생 printf
) 정의되지 않은 동작이 발생 합니다.
C 또는 다른 스택 기반 언어로 코딩 할 때 기억해야 할 매우 중요한 점은 함수가 반환되면 함수 (및 모든 로컬 저장소)가 사라진다는 것입니다. 즉, 다른 사람이 열심히 노력한 방법의 결과를 볼 수 있도록하려면 방법이 중단 된 후에도 계속 존재할 수있는 곳에 배치해야합니다. C가 물건을 저장하는 곳과 방법.
배열이 C에서 어떻게 작동하는지 이미 알고있을 것입니다. 이것은 객체의 크기만큼 증가하는 메모리 주소 일 뿐이며 C가 경계 검사를 수행하지 않는다는 것을 알고있을 것입니다. 따라서 10의 11 번째 요소에 액세스하려는 경우 요소 배열, 아무도 당신을 막을 수 없으며 아무것도 쓰지 않는 한 아무런 해를 끼치 지 않습니다. 여러분이 모를 수도있는 것은 C가이 아이디어를 함수와 변수를 사용하는 방식으로 확장한다는 것입니다. 함수는 요청시로드되는 스택의 메모리 영역 일 뿐이며 해당 변수에 대한 저장소는 해당 위치에서 오프셋됩니다. 함수가 지역 변수에 대한 포인터, 특히 'Hello World \ n \ 0'의 'H'를 보유하는 스택의 위치 주소를 반환했습니다. 그러나 다른 함수 (인쇄 메서드)를 호출했을 때 해당 메모리는 필요한 작업을 수행하기 위해 인쇄 메서드에 의해 재사용되었습니다. 쉽게 볼 수 있습니다 (프로덕션 코드에서는이 작업을 수행하지 마십시오 !!!).
char* foo2 = function2(); // Prints nothing
ch = foo2[0]; // Do not do this in live code!
printf("%s\n", foo2); // stack used by foo2 now used by print()
printf("ch is %c\n", ch); // will have the value 'H'!
I thought the return value of both of the functions would be undefined since they are returning data that is out of scope.
No. That's not the case.
In function function1
you are returning pointer to a string literal. Returning pointer to a string literal is fine because string literals have static storage duration. But that's not true with automatic local variable.
In function function2
the array string
is an automatic local variable and the statement
return string;
returns a pointer to an automatic local variable. Once the function return, the the variable string
will no longer exist. Dereferencing the returned pointer will cause undefined behavior.
"Hello, World!"
is a string literal, which has a static storage duration, so the problem is elsewhere. Your first function returns the value of string
, which is fine. The second function however returns the address of a local variable (string
is the same as &string[0]
), resulting in undefined behavior. Your second printf
statement could print nothing, or "Hello, World!", or something else entirely. On my machine, the program just gets a segmentation fault.
Always take a look at messages your compiler outputs. For your example, gcc
gives:
file.c:12:12: warning: function returns address of local variable [-Wreturn-local-addr]
return string;
^
which is pretty much self-explanatory.
I thought the return value of both of the functions would be undefined since they are returning data that is out of scope.
Both functions return a pointer. What matters is the scope of the referent.
In function1
, the referent is the string literal "Hello, World!"
, which has static storage duration. string
is a local variable which points to that string, and conceptually, a copy of that pointer is returned (in practice, the compiler will avoid unnecessarily copying the value).
In function2
, conceptually the referent is the local array string
, which has been automatically sized (at compile time) to be big enough to hold the string literal (including a null terminator, of course), and been initialized with a copy of the string. The function would return a pointer to that array, except that the array has automatic storage duration and thus no longer exists after exiting the function (it is indeed "out of scope", in more familiar terminology). Since this is undefined behaviour, the compiler may in practice do all sorts of things.
Does that mean that all
char*
are static?
Again, you need to distinguish between the pointer and the referent. Pointers point at data; they don't themselves "contain" the data.
You have reached a point where you should properly study what arrays and pointers actually are in C - unfortunately, it's a bit of a mess. The best reference I can offer offhand is this, in Q&A format.
'IT박스' 카테고리의 다른 글
RC.1에서는 바인딩 구문을 사용하여 일부 스타일을 추가 할 수 없습니다. (0) | 2020.11.15 |
---|---|
Promise catch에서 오류 다시 던지기 (0) | 2020.11.15 |
PHP의 Structs 데이터 유형? (0) | 2020.11.14 |
객체 / 인스턴스 / 변수의 존재를 우아하게 확인하고 파이썬에 존재하는 경우 변수에 동시에 할당하는 방법은 무엇입니까? (0) | 2020.11.14 |
mysql : 소스 오류 2? (0) | 2020.11.14 |