포인터는 C에서 참조로 호출하는 방법으로 간주됩니까?
내 대학의 C 프로그래밍 수업에서 교수와 그녀가 쓴 후속 책 은 C의 포인터 를 참조 할 때 호출 또는 참조로 전달 이라는 용어를 사용합니다 .
내 교수가 '참조 함수에 의한 호출'로 간주하는 예 :
int sum(int *a, int *b);
내 교수가 '가치 함수에 의한 호출'로 간주하는 예 :
int sum(int a, int b);
나는 C가 참조로 전화를 지원하지 않는다는 것을 읽었습니다 . 내 이해에 포인터는 값으로 전달됩니다 .
기본적으로 포인터가 참조로 전달되는 C의 방법이라고 말하는 것은 잘못된 것입니까? C에서 참조로 전달할 수는 없지만 포인터를 대안으로 사용할 수 있다고 말하는 것이 더 정확 할까요?
업데이트 11/11/15
내 질문이 시작된 방식에서 용어에 대한 논쟁이 생겼다고 생각하며 실제로 두 가지 구체적인 차이점을보고 있습니다.
- 참조에 의한 전달 (오늘날 주로 사용되는 용어) : C ++와 같은 언어에서 사용되는 특정 용어
- pass-by-reference (내 교수가 포인터를 설명하기위한 패러다임으로 사용하는 용어) : C ++와 같은 언어가 개발되기 전에 사용되어 용어가 다시 작성되기 전에 사용 된 일반적인 용어
@Haris의 업데이트 된 답변을 읽은 후 이것이 왜 그렇게 흑백이 아닌지 이해할 수 있습니다.
C에서 참조로 전달할 수는 없지만 포인터를 대안으로 사용할 수 있습니다.
네, 맞습니다.
좀 더 자세히 설명합니다. c 함수에 인수로 전달하는 것은 무엇이든 값으로 만 전달됩니다. 변수의 값 또는 변수 주소인지 여부.
차이를 만드는 것은 당신이 보내는 것입니다.
값으로 전달할 때 변수의 값을 함수에 전달합니다. 참조로 전달할 때 변수의 별칭을 함수에 전달합니다. C는 포인터를 함수에 전달할 수 있지만 여전히 값에 의한 전달입니다. 포인터의 값인 주소를 함수에 복사합니다.
변수 값을 보내는 경우 함수는 값만 수신하고이를 변경해도 원래 값에는 영향을주지 않습니다.
변수의 주소를 보내는 경우 값 (이 경우 주소) 만 보내지지만 변수의 주소가 있으므로 원래 값을 변경하는 데 사용할 수 있습니다.
예를 들어, 값별 호출과 참조 별 호출의 실제 차이점을 이해하기 위해 C ++ 코드를 볼 수 있습니다. 이 웹 사이트 에서 가져온 것 입니다.
// Program to sort two numbers using call by reference.
// Smallest number is output first.
#include <iostream>
using namespace std;
// Function prototype for call by reference
void swap(float &x, float &y);
int main()
{
float a, b;
cout << "Enter 2 numbers: " << endl;
cin >> a >> b;
if(a>b)
swap(a,b); // This looks just like a call-by-value, but in fact
// it's a call by reference (because of the "&" in the
// function prototype
// Variable a contains value of smallest number
cout << "Sorted numbers: ";
cout << a << " " << b << endl;
return 0;
}
// A function definition for call by reference
// The variables x and y will have their values changed.
void swap(float &x, float &y)
// Swaps x and y data of calling function
{
float temp;
temp = x;
x = y;
y = temp;
}
이 C ++ 예제에서는 참조 변수 (C에는 없음)가 사용됩니다. 이 웹 사이트 를 인용하려면
"참조는 별칭 또는 기존 변수에 대한 대체 이름입니다 ..." ,
과
"참조의 주요 용도는 참조에 의한 전달을 지원하는 함수 형식 매개 변수 역할을합니다 ..."
이것은 포인터를 함수 매개 변수로 사용하는 것과 다릅니다.
"포인터 변수 (또는 간단히 포인터)는 기본적으로 데이터를 저장할 수있는 다른 변수와 동일합니다. 값을 저장하는 일반 변수 (예 : int, double, char)와 달리 포인터는 메모리 주소. "
따라서 본질적으로 주소를 보내고 포인터를 통해 수신 할 때 하나는 값만 보내고 참조 변수를 보내고받을 때 하나는 별칭 또는 참조를 보내는 것입니다.
업데이트 : 2015 년 11 월 11 일
C Chatroom 에서 오랜 논쟁이 있었고이 질문에 대한 댓글과 답변을 읽은 후이 질문을 보는 또 다른 방법이 있다는 것을 깨달았습니다.
간단한 C 코드를 살펴 보겠습니다.
int i;
int *p = &i;
*p = 123;
이 시나리오에서는 p의 값이 i에 대한 참조 라는 용어를 사용할 수 있습니다 . 따라서이 경우 동일한 포인터 ( int* p
)를 함수에 i
보내면의 참조가 함수에 전송되므로 참조에 의한 전달 이라고 할 수 있습니다 .
그래서 그것은 용어와 시나리오를 보는 방법의 문제입니다.
나는 그 주장에 완전히 동의하지 않을 것입니다. 그러나 책과 규칙을 완전히 따르는 사람에게는 이것은 잘못된 것입니다.
참고 : 이 채팅에서 영감을 얻은 업데이트 입니다.
여기서 참조는 과부하 된 용어입니다. 일반적으로 참조는 단순히 무언가를 참조하는 방법입니다. 포인터는 가리키는 개체를 참조하며 개체에 대한 포인터를 값으로 전달하는 것이 C에서 참조로 전달하는 표준 방법입니다.
C ++는 참조를 표현하는 더 좋은 방법으로 참조 유형을 도입했으며, 기술 영어에 모호함을 도입했습니다. 이제 참조 유형을 사용하여 참조로 객체를 전달하는 것을 지칭하기 위해 "참조로 전달"이라는 용어를 사용할 수 있기 때문입니다.
C ++ 컨텍스트에서 이전 사용은 더 이상 사용되지 않는 IMO입니다. 그러나 나는 모호함이없는 다른 문맥 (예 : 순수 C)에서는 전자의 사용이 일반적이라고 생각합니다.
별로.
엄밀히 말하면 C는 항상 값으로 전달을 사용합니다. 포인터를 받아들이는 함수를 정의한 다음을
&
호출 할 때 연산자 를 사용하여 참조로 전달을 직접 시뮬레이션 할 수 있으며, 컴파일러는 함수에 배열을 전달할 때 기본적으로이를 시뮬레이션합니다 (포인터를 대신 전달하여 질문 6.4 참조). al.).이를 보는 또 다른 방법은 매개 변수에 유형
int *
이있는 경우 정수가 참조로 전달되고 정수에 대한 포인터가 value로 전달된다는 것입니다 .기본적으로 C에는 참조 또는 C ++ 참조 매개 변수에 의한 공식 전달과 진정으로 동등한 것은 없습니다 .
포인터가 값으로 전달됨을 보여주기 위해 포인터를 사용한 숫자 스와핑의 예를 살펴 보겠습니다.
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
int ptemp;
printf("Before swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
temp = pnum1;
pnum1 = pnum2;
pnum2 = ptemp;
printf("After swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Instead of swapping numbers pointers are swapped. Now make a function for the same
void swap(int *pnum1, int *pnum2)
{
int *ptemp = pnum1;
pnum1 = pnum2;
pnum2 = temp;
}
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
printf("Before swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
swap(pnum1, pnum2);
printf("After swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Boom! No swapping!
Some tutorials mention pointer reference as call by reference which is misleading. See the this answer for the difference between passing by reference and passing by value.
From the C99 standard (emphasis mine):
6.2.5 Types
20 Any number of derived types can be constructed from the object and function types, as follows:
...
— A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.
Based on the above, what your professor said makes sense and is correct. A pointer is passed by value to functions. If the pointer points to a valid entity, its value provides a reference to an entity.
"Passing by reference" is a concept. Yes, you are passing the value of a pointer to the function, but in that instance the value of that pointer is being used to reference the variable.
Someone else used a screwdriver analogy to explain that it is wrong to refer to the passing of pointers as passing by reference, saying that you can screw a screw with a coin but that that doesn't mean you would call the coin a screw driver. I would say that is a great analogy, but they come to the wrong conclusion. In fact, while you wouldn't claim a coin was a screwdriver, you would still say that you screwed the screw in with it. i.e. even though pointers are not the same as c++ references, what you are using them to do IS passing by reference.
C passes arguments by value, period. However, pointers are a mechanism that can be used for effectively passing arguments by reference. Just like a coin can be used effectively as a screw driver if you got the right kind of screw: some screws slit are even chosen to operate well with coins. They still don't turn the coins into actual screw drivers.
C++ still passes arguments by value. C++ references are quite more limited than pointers (though having more implicit conversions) and cannot become part of data structures, and their use looks a lot more like the usual call-by-reference code would look, but their semantics, while very much catered to match the needs of call-by-reference parameters, are still more tangible than that of pure call-by-reference implementations like Fortran parameters or Pascal var
parameters and you can use references perfectly well outside of function call contexts.
Your professor is right. By value , it is copied. By reference, it is not copied, the reference says where it is.
By value , you pass an int to a function , it is copied , changes to the copy does not affect the original.
By reference , pass same int as pointer , it is not copied , you are modifying the original.
By reference , an array is always by reference , you could have one billion items in your array , it is faster to just say where it is , you are modifying the original.
In languages which support pass-by-reference, there exists a means by which a function can be given something that can be used to identify a variable know to the caller until the called function returns, but which can only be stored in places that won't exist after that. Consequently, the caller can know that anything that will be done with a variable as a result of passing some function a reference to it will have been done by the time the function returns.
Compare the C and C# programs:
// C // C#
int x=0; int x=0;
foo(&x); foo(ref x);
x++; x++;
bar(); bar();
x++; x++;
boz(x); boz(x);
The C compiler has no way of knowing whether "bar" might change x, because foo() received an unrestricted pointer to it. By contrast, the C# compiler knows that bar() can't possibly change x, since foo() only receives a temporary reference (called a "byref" in .NET terminology) to it and there is no way for any copy of that byref to survive past the point where foo() returns.
Passing pointers to things allows code to do the same things that can be done with pass-by-ref semantics, but pass-by-ref semantics make it possible for code to offer stronger guarantees about things it won't do.
'IT박스' 카테고리의 다른 글
Stata 소프트웨어없이 dta 파일을 csv로 변환 (0) | 2020.11.17 |
---|---|
Qt. (0) | 2020.11.17 |
'?'는 무엇입니까? (0) | 2020.11.17 |
Android EditText에서 수직 콘텐츠 정렬 (0) | 2020.11.17 |
sqlite 한 테이블에서 다른 테이블로 데이터 복사 (0) | 2020.11.17 |