이름이나 유형에 특정 언어 연결이 있다는 것은 무엇을 의미합니까?
(c) ANSI ISO/IEC 14882:2003에 따라 127페이지:
링크 사양이 중첩됩니다.링크 사양이 중첩될 때 가장 안쪽에 있는 것이 언어를 결정합니다.링크 사양은 범위를 설정하지 않습니다.연결 사양은 네임스페이스 범위(3.3)에서만 발생해야 합니다.연결 규격에서 지정된 언어 연결은 선언에 의해 도입된 모든 함수 선언자, 함수 이름 및 변수 이름의 함수 유형에 적용됩니다.
extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function
extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage
extern "C" FUNC f3;
// the name of function f3 and the function's type
// have C language linkage
void (*pf2)(FUNC*);
// the name of the variable pf2 has C++ linkage and
// the type of pf2 is pointer to C++ function that
// takes one parameter of type pointer to C function
이 모든 것이 무엇을 의미합니까?를 들어, 예들어, 어연이는 어떤 을 합니까?f2()
C 또는 C++ 언어 연결 기능이 있습니까?
@Johannes Schaub가 지적한 바와 같이, 이것이 무엇을 의미하는지에 대한 실제적인 설명은 표준에 없으므로 컴파일러마다 다르게 해석될 수 있습니다.
개체 파일의 차이점을 설명하십시오.
- C 언어 연결과 C++ 언어 연결이 있는 함수의 이름입니다.
- C 언어 연결과 C++ 언어 연결이 있는 함수 유형입니다.
언어 연결은 다음 사이의 연결에 사용되는 용어입니다.C++
그리고.non-C++
일반적으로 이름,, 이름에도 연결이 .일반적으로 C++ 프로그램에서는 모든 함수 이름, 함수 유형 및 변수 이름에 기본 C++ 언어 연결이 있습니다.
하여 생성되는 다른 객체 코드와 연결될 수 있습니다(예: C++ 사언생소스다있어니수습다객연용른성를체여하다는른결객되될체코드와드는코▁c▁a▁code▁which▁(▁objectlike다▁language니▁can▁code객있습▁some).C
미리 정의된 링크 지정자를 사용합니다.
다음의 개념을 알고 있어야 합니다.name mangling
함수 이름, 함수 유형 및 변수 이름을 인코딩하여 고유한 이름을 생성합니다.이를 통해 링커는 공통 이름을 구별할 수 있습니다(함수 오버로드의 경우처럼).C 모듈을 C++ 컴파일러로 컴파일된 라이브러리 또는 개체 파일과 연결할 때 이름 망글링은 바람직하지 않습니다.이러한 경우 이름 망글을 방지하기 위해 연결 지정자가 사용됩니다. 이경에는우,,extern "C"
는 연결 지정자입니다.예를 들어 보겠습니다(여기에 언급된 c++ 코드).
typedef int (*pfun)(int); // line 1
extern "C" void foo(pfun); // line 2
extern "C" int g(int) // line 3
...
foo( g ); // Error! // line 5
1호선은 다음을 선언합니다.pfun
연결 지정자가 없기 때문에 C++ 함수를 가리킵니다.
따라서 라인 2는 foo를 C++ 함수로 포인터를 가져오는 C 함수라고 선언합니다.
5호선은 g, C 함수, 유형 불일치에 대한 포인터로 foo를 호출하려고 합니다.
함수 이름 연결의 차이:
두 개의 다른 파일을 사용해 보겠습니다.
가 있는 것extern "c"
파일(file1.cpp):
#include <iostream>
using namespace std;
extern "C"
{
void foo (int a, int b)
{
cout << "here";
}
}
int main ()
{
foo (10,20);
return 0;
}
가 없는 것.extern "c"
파일(file2.cpp):
#include <iostream>
using namespace std;
void foo (int a, int b)
{
cout << "here";
}
int main ()
{
foo (10,20);
return 0;
}
이제 이 두 가지를 컴파일하고 objdump를 확인합니다.
# g++ file1.cpp -o file1
# objdump -Dx file1
# g++ file2.cpp -o file2
# objdump -Dx file2
연결을 사용하는 경우 "C"에 이름 망글링이 .foo
이것을은 (할 수 .dlsym
그리고.dlopen
하지 않음.) 어떤 이름의 망글링 효과도 고려하지 않았습니다.
0000000000400774 <foo>:
400774: 55 push %rbp
400775: 48 89 e5 mov %rsp,%rbp
....
....
400791: c9 leaveq
400792: c3 retq
0000000000400793 <main>:
400793: 55 push %rbp
400794: 48 89 e5 mov %rsp,%rbp
400797: be 14 00 00 00 mov $0x14,%esi
40079c: bf 0a 00 00 00 mov $0xa,%edi
4007a1: e8 ce ff ff ff callq 400774 <foo>
4007a6: b8 00 00 00 00 mov $0x0,%eax
4007ab: c9 leaveq
면에반이 때는 지않을때그.extern "C"
입니다. 사용중중, func:foo
규칙 중인 있음)으로이을 직접 할 수 이름을(를) 지정할 수 .foo
하지만 당신은 그것을 망가진 이름으로 부를 수 있습니다 (_Z3fooii
만약 당신이 원한다면, 하지만 아무도 명백한 이유로 그것을 사용하지 않습니다.
0000000000400774 <_Z3fooii>:
400774: 55 push %rbp
400775: 48 89 e5 mov %rsp,%rbp
...
...
400791: c9 leaveq
400792: c3 retq
0000000000400793 <main>:
400793: 55 push %rbp
400794: 48 89 e5 mov %rsp,%rbp
400797: be 14 00 00 00 mov $0x14,%esi
40079c: bf 0a 00 00 00 mov $0xa,%edi
4007a1: e8 ce ff ff ff callq 400774 <_Z3fooii>
4007a6: b8 00 00 00 00 mov $0x0,%eax
4007ab: c9 leaveq
4007ac: c3 retq
이 페이지는 이 특정 주제에 대해서도 좋은 읽을거리입니다.
전화 회의에 대한 멋지고 명확하게 설명된 기사: http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx
"이름 f2는 C++ 언어 연결을 가지고 있습니다." C++ 언어 연결에서는 함수의 이름뿐만 아니라 인수의 유형과 반환 값도 정의합니다.이 경우: void f2(void); 하지만 그것으로 정의할 수 있습니다: void f2(inta); 링크가 그들을 다른 유형으로 볼 것이기 때문에 충돌 없이, C 언어로는 할 수 없는 것입니다.
"함수의 유형은 C 언어 연결이 있습니다." 자세한 내용은 모르지만 높은 수준은 알고 있습니다.기본적으로 C++ 컴파일된 함수를 C에서 연결할 수 있게 합니다.C와 C++에서 매개 변수가 함수로 전달되는 방식이 다르다는 것을 정확히 기억한다면,이 경우 함수 f2는 C 컴파일러가 이를 수행하는 것처럼 매개 변수를 전달합니다.이렇게 하면 C와 C++ 모두에서 함수를 연결할 수 있습니다.
extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage
이름은 은이름입니다.FUNC
다음과 같이 표시되므로 "C" 연결로 선언됩니다.extern "C"
이름은 은이름입니다.f2
는 C++ 연결을 가지고 있으며, 이 연결은 기본값이며 다른 연결은 2행에 제공되지 않습니다.
그이이라는 이 있다는 f2
는 C 연결이 있는 함수를 나타내는 데 사용되며 이름의 연결은 변경되지 않습니다.
그것은 프로그램의 ABI(Application Binary Interface)와 관련이 있습니다.
API가 프로그램의 소스 코드의 외부 인터페이스를 지정하면 ABI는 프로그램의 바이너리 코드(컴파일된 버전)의 외부 인터페이스를 지정합니다.
원래, C 함수는 몇 가지 다른 형태를 가지고 있었습니다.비슷한 것
int foo(int);
컴파일러에 의해 언더스코어로 접두사가 붙어서 형성될 것입니다._foo
다른 응용 프로그램에서 사용할 수 있도록 내보냅니다.
하지만, 그것은 충분하지 않았습니다.예를 들어, Windows API를 보면 다음과 같은 것들을 볼 수 있습니다.
DWORD CreateWindowW(...); //Original parameters
DWORD CreateWindowExW(..., ...); //More parameters
를 구분할에 사람들은 함수의 를 바꾸기 했습니다.Ex
접미사(또는 그와 유사함)
이것은 꽤 추악하게 커졌고, 여전히 C++에서 특징적인 연산자 오버로드를 허용하지 않았습니다.이것 때문에, C++는 함수의 이름에 추가적인 정보를 넣기 위해 이름 망글링을 생각해냈습니다. 예를 들어 매개 변수의 데이터 유형과 같은 정보를 추가하고, 많은 정보를 포함하는 암호화된 것으로 만들기 위해서입니다.@
기호
완전히 표준화되지 않은 것을 제외하고는 모두 좋았습니다.
물론, 새로운 언어와 컴파일러가 등장함에 따라, 각 언어는 다른 언어와 호환되지 않는 독자적인 계획을 생각해 냈습니다.함수를 경우 해야 하기 에 따서외함부가수져있필내경요컴라는검합하다니야유색지우야는형해을정해파러가일가보를오 ABI거나낼▁so다합▁should니,▁thei야▁what▁you▁hence▁an해▁compiler▁function▁youi▁or▁if▁export▁need따라.extern "C++"
당신은 거기 있습니다.
이 모든 것이 무엇을 의미합니까?예를 들어, f2() 함수에는 C 또는 C++ 언어 연결 중 어떤 연결이 있습니까?
extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage
당신이 "f2() 함수"라고 부르는 것은 연결에 두 가지 측면이 있습니다.
- 기호 테이블(C++ 언어 연결이 있는)에서 이름의 망글링 여부 및
- C 또는 C++ 호출 규약은 함수를 (C)라고 불러야 합니다.
에 f2()
개체 파일에서 이 이름의 기호를 찾을 수 있습니다. 이 기호는 "f2라는 이름의 함수가 인수를 사용하지 않음"의 망가진 버전이 될 것입니다.할 수 GNU tools 위의컴예개고파검체이를사를사사용다있수확니습방도인구할소식으로한하면: GNU 코드하를일예▁you사용▁gnue).nm --demangle
).
그러나 함수를 호출하기 위해, 사전 및 사후 조건 레지스터 사용, 스택 설정 등에 대한 규칙은 C 함수의 규칙입니다.C와 C++ 함수가 서로 다른 호출 규칙을 갖는 것은 합법적이며, 예를 들어 C++ 예외 처리를 용이하게 하기 위해 수행될 수 있습니다.
오브젝트 파일의 차이점을 설명해주세요: C 언어 연결과 C++ 언어 연결을 가진 함수의 이름.
- C 연결의 경우, "f2"는 다음과 같은 결과를 가져오는 객체 파일의 기호가 될 것입니다.
f2()
- " 않는 f2라는 이름의 함수(GNU의 C++ 링인수를라경우의, "f2 의는이는함름수의하", "f2 않지버경우전"),
_Z2f2v
그것은 다음과 같은 것입니다.f2()
)
C 언어 연결과 C++ 언어 연결이 있는 함수 유형입니다.
위에서 논의한 바와 같이, 이것은 함수의 주소로 코드를 호출하기 위한 레지스터/스택 사용 규약에 관한 것입니다.이 메타 정보는 반드시 개체의 기호 테이블 정보에 저장되지는 않으며 기호 이름 키 자체의 일부도 아닙니다.
또한 각 함수는 호출 규칙 중 하나를 채택하기 때문에 컴파일러는 함수에 대한 포인터를 따를 때 사용할 호출 규칙을 알아야 합니다. 이러한 통찰력으로 질문에 남아 있는 코드가 명확해졌다고 생각합니다.
http://developers.sun.com/solaris/articles/mixing.html 에서 훌륭한 토론을 하고 있습니다. 특히 기능에 대한 포인터 작업 섹션을 추천합니다.
C/C++ 코드 변환은 컴파일과 링크라는 두 가지 주요 단계로 구성되어 있습니다.컴파일러가 객체 파일을 생성할 때 주어진 함수가 호출되거나 참조되는 객체 파일을 지정하는 링커에 정보를 전달합니다.C에서 함수는 이름과 일치하는 정의를 가지고 있습니다.
// file1.c
void foo(void) {}
컴파일 후 file1.obj는 foo 기호의 정의에 대한 코드와 정보를 저장합니다.
하지만 C++가 들어오면 기호 이름이 더 복잡해집니다.함수가 오버로드되었거나 클래스의 구성원일 수 있습니다.하지만 링커는 그것을 알고 싶어하지 않습니다.오래된 링커의 단순성과 재사용 가능성을 유지하기 위해서는 foo가 다음과 같은 단일 이름이 필요합니다.
void foo(void) {}
void foo(int) {}
void ClassA::foo(void) {}
하지만 더 이상 foo라고 부를 수 없기 때문에 mangling이라는 이름이 나옵니다.그리고 컴파일러에서 foo_void, foo_int, foo_void_classa와 같은 변형을 얻을 수 있습니다.그리고 마지막으로 링커는 단순한 기호처럼 보이기 때문에 행복합니다.
C++ 코드에서 C 컴파일러로 컴파일된 foo 함수를 호출하고 싶을 때, 우리는 C++ 컴파일러가 가정하는 foo_void가 아닌 C 스타일 foo가 되기를 원한다고 컴파일러에게 말해야 합니다.이 작업은 다음을 사용하여 수행됩니다.
extern "C" void foo();
이제 컴파일러는 foo가 C 컴파일러를 사용하여 컴파일된다는 것을 알고 있으며 이 코드가 foo라고 부르는 정보를 링커에 전달합니다.링커는 파일 1.obj의 foo 정의와 일치합니다.그게 제 생각의 전부입니다.
cdecl 또는 stdcall과 같은 일부 다른 지침은 Windows에 고유하며 함수 호출의 매개 변수가 전달되는 방식을 알려줍니다.예, C와 C++의 경우 cdecl입니다.그러나 Windows API 함수는 stdcall - Pascal 규약을 사용합니다(단순함과 역사적으로 Microsoft는 한때 Pascal에서 Windows 개발 환경을 제공했습니다).
모든 함수, 함수 유형 및 개체에는 단순 문자열로 지정된 언어 연결이 있습니다.기본적으로 연결은 "C++"입니다.유일한 다른 표준 언어 연결은 "C"입니다.다른 모든 언어 연결 및 다른 언어 연결과 관련된 속성은 구현 정의됩니다.
언급URL : https://stackoverflow.com/questions/5763919/what-does-mean-for-a-name-or-type-to-have-a-certain-language-linkage
'programing' 카테고리의 다른 글
여러 저장 프로시저의 결과 연합 (0) | 2023.08.04 |
---|---|
키워드 "weak"을 클래스 및 클래스 바인딩 프로토콜 유형에만 적용할 수 있는 이유는 무엇입니까? (0) | 2023.08.04 |
Invoke-WebRequest : '헤더' 매개 변수를 바인딩할 수 없습니다. (0) | 2023.07.30 |
파이썬 스크립트를 이진 실행 파일로 컴파일하는 방법 (0) | 2023.07.30 |
JavaScript를 사용한 서버 폴링 (0) | 2023.07.30 |