[c] 왜 타입이 아닌 변수 이름 앞에 별표가 나타나는가?

왜 대부분의 C 프로그래머가 다음과 같이 변수 이름을 지정합니까?

int *myVariable;

이보다는

int* myVariable;

둘 다 유효합니다. 별표는 변수 이름의 일부가 아닌 유형의 일부인 것 같습니다. 누구든지이 논리를 설명 할 수 있습니까?



답변

그것들은 정확히 동등합니다. 그러나

int *myVariable, myVariable2;

myVariable의 유형은 int * 이지만 myVariable2의 유형은 int 입니다. 에

int* myVariable, myVariable2;

그것은 모두가 형의 것을 분명 보일 수 INT의 * 하지만, 같은 그것은 정확하지 않은 myVariable2타입이 INT를 .

따라서 첫 번째 프로그래밍 스타일이 더 직관적입니다.


답변

다른 방법으로 살펴보면 *myVariable유형이 int있습니다.


답변

해당 행의 *는 유형보다 변수에 더 가깝게 바인딩되므로

int* varA, varB; // This is misleading

@Lundin이 아래에서 지적한 것처럼 const는 더 많은 미묘함을 추가합니다. 한 줄에 하나의 변수를 선언하여이를 완전히 회피 할 수 있습니다.

int* varA;
int varB;

명확한 코드와 간결한 코드 사이의 균형은 깨지기 어렵습니다. 12 줄의 중복 된 줄도 int a;좋지 않습니다. 여전히, 나는 한 줄에 하나의 선언을 기본으로하고 나중에 코드를 결합하는 것에 대해 걱정합니다.


답변

지금까지 아무도 언급하지 않은 것은이 별표가 실제로 C에서 ” 역 참조 연산자 “라는 것입니다.

*a = 10;

선 위의 I 할당 할 것을 의미하지 않는다 10a, 내가 할당 할 뜻 10대로 메모리 위치를 a가리 킵니다. 그리고 나는 글을 쓰는 사람을 본 적이 없다

* a = 10;

당신은? 따라서 역 참조 연산자 는 항상 공백없이 작성됩니다. 이것은 아마 여러 줄에 걸쳐 곱셈과 구별되는 것일 것입니다.

x = a * b * c * d
  * e * f * g;

여기 *e그것은하지 않을 오해의 소지가 될 것이다?

이제 다음 줄은 실제로 무엇을 의미합니까?

int *a;

대부분의 사람들은 다음과 같이 말합니다.

이는 값에 a대한 포인터 임을 의미합니다 int.

이것은 기술적으로 정확하며 대부분의 사람들은 그것을 그렇게 읽거나 읽는 것을 좋아하며 이것이 현대 C 표준이 그것을 정의하는 방식입니다 (언어 C 자체는 모든 ANSI 및 ISO 표준보다 우선합니다). 그러나 그것을 보는 유일한 방법은 아닙니다. 이 줄을 다음과 같이 읽을 수도 있습니다.

의 역 참조 된 값은 a유형 int입니다.

따라서 실제로이 선언에서 별표는 역 참조 연산자로 표시 될 수 있으며이 연산자는 배치를 설명합니다. 그리고 그것은 a포인터가 실제로 선언되지 않았으며, 실제로 당신이 실제로 역 참조 할 수있는 유일한 것은 포인터라는 사실에 의해 암시 적입니다.

C 표준은 *운영자 에게 두 가지 의미 만 정의합니다 .

  • 간접 연산자
  • 곱셈 연산자

그리고 간접는 단지 하나의 의미는 별도의 의미는 포인터를 선언하는가이다, 참조 취소 조작이하는 일,이 같은 문 이내에 또한, 간접적 인 접근을 수행 다만 간접,이 int *a;이 간접적 인 액세스 ( *수단 간접 액세스) 따라서 위의 두 번째 진술은 첫 번째 진술보다 표준에 훨씬 가깝습니다.


답변

여기에서 사지로 나가서 변수 선언과 매개 변수 및 반환 유형 모두에 대해이 질문에 대한 정답이 있다고 말합니다. 즉 별표가 이름 옆에 있어야합니다 int *myVariable;. 이유를 이해하려면 C에서 다른 유형의 기호를 선언하는 방법을 살펴보십시오.

int my_function(int arg); 기능을 위해;

float my_array[3] 배열.

선언은 use 다음에 나오는 일반적인 패턴으로, 심볼의 유형은 이름 앞 부분과 이름 주위 부분으로 나뉘며 이름 주위 의 이러한 부분은 왼쪽에있는 유형의 값 :

int a_return_value = my_function(729);

float an_element = my_array[2];

그리고 : int copy_of_value = *myVariable;.

참조를 사용하는 지점의 구문이 값 유형의 구문과 동일하므로 C ++은 참조 작업에 스패너를 던지므로 C ++이 C에 대해 다른 접근 방식을 취한다고 주장 할 수 있습니다. 반면에 C ++은 동일하게 유지됩니다. 포인터의 경우 C의 동작이므로 참조는 실제로이 점에서 이상한 것입니다.


답변

그것은 단지 선호의 문제입니다.

코드를 읽을 때 두 번째 경우 변수와 포인터를 구분하는 것이 더 쉽지만, 공통 유형의 변수와 포인터를 한 줄에 넣을 때 혼동을 일으킬 수 있습니다. 가독성이 떨어지기 때문에).

유형 이름 옆에 해당 기호로 포인터를 선언하는 것을 선호합니다.

int* pMyPointer;


답변

한 위대한 전문가는 “컴파일러의 방식을 읽으십시오.”라고 말했습니다.

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

이것이 const 배치에 관한 것이 었음에도 동일한 규칙이 적용됩니다.

컴파일러는 다음과 같이 읽습니다.

int (*a);

로 :

(int*) a;

변수 옆에 별을 배치하는 습관을 들이게되면 선언을보다 쉽게 ​​읽을 수 있습니다. 또한 다음과 같은 눈가리개를 피합니다.

int* a[10];

— 편집하다 —

나는로서 해석 말할 때 무슨 뜻인지 정확히 설명하는 int (*a)수단 있다는 것을, *보다 긴밀하게 결합 a은보다가 int, 매우 방식으로 발현에 있음을 4 + 3 * 7 3보다 긴밀하게 결합 7이보다 할 4의 높은 우선 순위로 인해 *.

ascii art에 대한 사과와 함께 파싱을위한 AST의 개요 int *a는 대략 다음과 같습니다.

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

명확하게 보여지는 바와 같이, 그들의 공통 조상이 있기 때문에 *더 밀접하게 묶는 반면, 당신은 나무를 올라가서 공통 조상을 찾아야합니다 .aDeclaratorDeclarationint