C에 화살표(->) 연산자가 존재하는 이유는 무엇입니까?
. 연산자는 구조체의 멤버에 액세스하기 위해 사용됩니다.->C의 )는 해당 포인터에 의해 참조되는 구조체의 멤버에 액세스하기 위해 사용됩니다.
포인터 자체에는 닷 연산자로 액세스할 수 있는 멤버가 없습니다(실제로 가상 메모리의 위치를 나타내는 숫자일 뿐이므로 멤버가 없습니다).따라서 포인터(컴파일 시 컴파일러가 알고 있는 정보)에서 사용되는 경우 포인터를 자동으로 참조 해제하도록 닷 연산자를 정의하면 모호함이 없습니다.
그런데 왜 언어 창작자들은 불필요해 보이는 연산자를 추가함으로써 일을 더 복잡하게 만들기로 결정했을까요?설계상의 중요한 결정사항은 무엇입니까?
은 두 왜?-> 존재 2) 왜'가 되는가 2).는 포인터를 자동으로 참조 해제하지 않습니다.두 질문에 대한 답은 모두 역사적 뿌리를 가지고 있다.
?는 왜?->할 수 있을까?
C 언어의 최초 버전 중 하나(1975년 5월에 6번째 에디션 Unix와 함께 제공된 "C 레퍼런스 매뉴얼"의 CRM이라고 함)에서 연산자는->와 동의어가 아닌 매우 배타적인 의미가 있었다* ★★★★★★★★★★★★★★★★★」.
CRM에 의해 묘사된 C언어는 많은 면에서 현대의 C언어와 매우 달랐다.CRM 구조 멤버는 타입 제한 없이 임의의 주소 값에 추가할 수 있는 글로벌한 바이트오프셋 개념을 구현했습니다.즉, 모든 구조 부재의 모든 이름은 독립적인 전역적 의미를 가집니다(따라서 고유해야 함).예를 들어 다음과 같이 선언할 수 있습니다.
struct S {
int a;
int b;
};
및 and and anda 0, name은 offset .b 2(오프셋 2(오프셋 2)는 2(오프셋 2)를 .int 내의 에게 고유 값을 입니다.예를 추가로 선언할 수 동일한 으로 합니다.
struct X {
int a;
int x;
};
그것도 괜찮겠지, 왜냐면 이름이a는 항상 01을 . 이
struct Y {
int b;
int a;
};
시도했으므로 .a 2 및 '오프셋2'로서b0으로 하다
여기가 '아예'가 있는 입니다.->오퍼레이터가 들어옵니다.가 있기 에서는 이러한 했습니다.
int i = 5;
i->b = 42; /* Write 42 into `int` at address 7 */
100->a = 0; /* Write 0 into `int` at address 100 */
번째 "take address"로되었습니다.5 offset , " " " "2을 할당하다42int값"을 입력합니다.즉, 상기의 할당은42로로 합니다.int의 값 " " "7의 이 해 주세요.->왼쪽의 표현 유형에 대해서는 신경쓰지 않았습니다.왼쪽은 rvalue 수치 주소(포인터 또는 정수)로 해석되었습니다.
이런 종류의 속임수는 다음 방법으로는 가능하지 않았다.* ★★★★★★★★★★★★★★★★★」.할 수 없다
(*i).b = 42;
*i는 이미 유효하지 않은 표현입니다.*는 '오퍼레이터'와는 .는 오퍼랜드에 보다 엄격한 타입 요건을 부과합니다.이 하기 위한 하기 위해 CRM은 CRM을 했습니다.->연산자: 왼쪽 피연산자의 유형과 독립적입니다.
했듯이 Keith의 는 Keith의 차이입니다.-> ★★★★★★★★★★★★★★★★★」*+.조합은 7.1.8에서 CRM이 '요건의 완화'라고 언급하고 있는 것입니다.포인터 타입의 요건의 완화를 제외하고, 이 표현은 다음과 같습니다.
이후 K&R C에서는 CRM에 원래 기술된 많은 기능이 대폭 수정되었습니다."구성부재를 글로벌 오프셋 식별자로"라는 개념은 완전히 제거되었습니다. ,, 능의 ->가 산자는는 operatoralityalityalityalityalityalityalityalityalityalityality의 기능과 일치하게 .* ★★★★★★★★★★★★★★★★★」.콤비네이션.
안 .포인터를 자동으로 참조 해제하시겠습니까?
에도 CRM의 언어에서는 CRM의 .연산자는 lvalue여야 합니다.그것이 그 오퍼랜드에 부과된 유일한 요건이었다(그것이 오퍼랜드와 다른 점이었다).->(상기와 같이).CRM은 왼쪽 오퍼랜드가 필요없다는 점에 주의해 주세요..구조 타입을 가지기 위해서.그냥 lvalue, 임의의 lvalue로 하면 됩니다.즉, CRM 버전에서는 다음과 같이 코드를 작성할 수 있습니다.
struct S { int a, b; };
struct T { float x, y, z; };
struct T c;
c.b = 55;
는 이우음음 음음음음 음음음 in음 in in in in in in in in in in in in in in in 。55 int'2'로 수 c라고 하는 타입이지만, 「」는 「」입니다.struct T라는 이름의 필드가 없었다.b 쓰지 c 쓴 건 오직...c 블록lvalue: 기가가가가가 block was was was was was was 。
이렇게 하면
S *s;
...
s.b = 42;
됩니다.s또한 lvalue)이며 컴파일러는 단순히 포인터 자체에 데이터를 쓰려고 시도합니다.말할 필요도 없이, 이러한 것들은 기억력의 초과를 초래하기 쉽지만, 언어 자체는 그런 문제에 관여하지 않았다.
연산자에 입니다..의 경우 : 연산자: 연산자: 연산자:.(lvalue pointer 또는 lvalue와 함께) 포인터와 함께 사용할 때 이미 매우 구체적인 의미가 있습니다.그것은 의심할 여지 없이 매우 이상한 기능이었다.을 사용법
이 이 과부하 상태인 것을 ..C - K&R C의 재작업 버전에서 포인터의 연산자(제안하신 대로)를 지정합니다. 그러나 아직 수행되지 않았습니다.CRM 버전으로 작성된 레거시 코드가 지원되어야 할 수도 있습니다.
(1975 C 참조 매뉴얼의 URL이 불안정할 수 있습니다.약간의 미묘한 차이가 있을 수 있는 다른 사본이 여기에 있습니다.)
과거의 (적합하고 이미 보고된) 이유를 넘어 연산자 우선 순위에도 약간의 문제가 있습니다. 점 연산자는 별 연산자보다 우선 순위가 높기 때문에 구조 포인터를 포함하는 구조체 포인터가 있는 경우...이 두 가지는 동일합니다.
(*(*(*a).b).c).d
a->b->c->d
하지만 두 번째는 확실히 더 읽기 쉽다.화살표 연산자는 가장 높은 우선 순위(점처럼)를 가지며 왼쪽에서 오른쪽으로 연관됩니다.이것은 구조물에 대한 포인터와 구조물에 대한 포인터 모두에 점 연산자를 사용하는 것보다 더 명확하다고 생각합니다. 왜냐하면 우리는 선언문을 볼 필요 없이 식에서 유형을 알 수 있고 다른 파일에 있을 수도 있기 때문입니다.
C도 애매모호하지 않게 잘해요.
두 가지 의미를 모두 나타내도록 점이 오버로드될 수 있지만, 이 화살표는 프로그래머가 포인터로 동작하고 있음을 알 수 있도록 합니다.이것은 컴파일러가 호환되지 않는 두 가지 타입을 혼재시키지 않도록 하는 것과 같습니다.
언급URL : https://stackoverflow.com/questions/13366083/why-does-the-arrow-operator-in-c-exist
'source' 카테고리의 다른 글
| Store vuex가 정의되지 않은 속성 'store'를 읽을 수 없습니다." (0) | 2022.08.10 |
|---|---|
| libcurl 없이 C에서 HTTP get 요구를 작성하려면 어떻게 해야 합니까? (0) | 2022.08.10 |
| C/C++ 매크로의 쉼표 (0) | 2022.08.10 |
| C의 단일 구조 부재 크기 (0) | 2022.08.10 |
| Java에서 데몬 스레드란 무엇입니까? (0) | 2022.08.10 |