아스타리스크는 왜 유형 뒤에가 아니라 변수 이름 앞에 있는 것입니까?
대부분의 C 프로그래머가 변수의 이름을 다음과 같이 짓는 이유는 무엇입니까?
int *myVariable;
이렇게 하는 것이 아니라:
int* myVariable;
둘 다 유효합니다.아스타리스크는 변수 이름의 일부가 아니라 유형의 일부인 것 같습니다.이 논리를 설명할 수 있는 사람이 있나요?
이들은 정확히 동등합니다.단,
int *myVariable, myVariable2;
myVariable의 타입은 int*이고 myVariable2의 타입은 int입니다.인
int* myVariable, myVariable2;
둘 다 int*형이라고 생각될 수 있지만, 이는 로서 올바르지 않습니다.myVariable2타입 int 입니다.
따라서 첫 번째 프로그래밍 스타일이 더 직관적입니다.
, 른른른 if if if if if if if if if if if if if if.*myVariable은 「」입니다.int일리가 있네요
여기서 아무도 언급하지 않은 것은 이 별표가 실제로는 C의 "참조 해제 연산자"라는 것입니다.
*a = 10;
이 제가 할당하고 것은 10로로 합니다.a , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,10의 위치까지a가리키고 있습니다. 글을 은 본 이 없어요.
* a = 10;
당신은 잡혔습니까?따라서 참조 해제 연산자는 거의 항상 공백 없이 작성됩니다.이것은, 복수의 행에 걸쳐 분할된 곱셈과 구별하기 위해서일 가능성이 있습니다.
x = a * b * c * d
* e * f * g;
서 ★★★★*e해의소 지지는 ,, 、 렇??
자, 다음 행은 실제로 무엇을 의미합니까?
int *a;
대부분의 사람들은 이렇게 말합니다.
, ,, ,, ,, ,, ,, ,.a is is is is is is is 。intdiscloss.discloss 。
이것은 기술적으로 옳습니다.대부분의 사람들은 그것을 그렇게 보고 읽는 것을 좋아합니다.이것은 현대의 C 표준이 정의하는 방법입니다(언어 C 자체가 모든 ANSI 및 ISO 표준보다 우선합니다).하지만 그것만이 유일한 방법은 아니다.이 행은 다음과 같이 읽을 수도 있습니다.
되지 않은 값 " " " " "a은 「」입니다.int.
따라서 이 선언의 별표는 참조 해제 연산자로도 볼 수 있으며, 이 연산자의 위치도 설명됩니다. 그 ★★★★★★★★★★★★★★★★★.a이치노이치노실제로 참조 해제할 수 있는 것은 포인터뿐입니다.
에서는 C의 2가지 하고 있습니다.*★★★★★★★★★★★★★★★★★★:
- 간접 연산자
- 곱셈 연산자
에, 「indirection」과 같은 에서도 행해집니다.단순한 간접이 있을 뿐입니다.이것은 디레퍼런스 조작이 하는 것입니다.즉, 간접적인 액세스가 실행됩니다.따라서 다음과 같은 스테이트먼트 내에서도 마찬가지입니다.int *a;이것은 간접적인 액세스입니다(*의 두 번째은 첫 .따라서 위의 두 번째 문장은 첫 번째 문장에 비해 표준에 훨씬 더 가깝습니다.
★★★★★★★를 선호하는 사람int* x;타입은 왼쪽에, 식별자(이름)는 오른쪽에 있는 가상의 세계로 코드를 강제하려고 합니다.
내가 "픽션"이라고 말하는 이유는:
C 및 C++에서는 일반적으로 선언된 식별자가 유형 정보로 둘러싸여 있습니다.
미친 소리처럼 들릴지 모르지만, 사실인 걸 알잖아요.다음은 몇 가지 예입니다.
int main(int argc, char *argv[])'는 '다'main를 필요로 하는 함수입니다.int을 나타냅니다.charand and and및다 an 。int즉, 대부분의 타입 정보는 오른쪽에 있습니다.어떤 사람들은 함수 선언이 특별한 것이기 때문에 중요하지 않다고 생각합니다. 좋아요, 변수를 시도해 봅시다.void (*fn)(int)「」를 의미합니다.fn는, 을 입니다.int이치노int a[10]는 10의 을 'a'로 하여 선언합니다.ints.pixel bitmap[height][width].분명히, 나는 내 주장을 뒷받침하기 위해 많은 유형 정보가 있는 예시를 골랐다.이 많이 .
struct { int x; int y; } center.
이 선언문 구문은 선언문에 용법을 반영시키고자 하는 K&R의 바람에서 비롯되었다.간단한 선언을 읽는 것은 직관적이며, 더 복잡한 선언을 읽는 것은 오른쪽-왼쪽-오른쪽 규칙을 배우는 것으로 숙달될 수 있습니다(나선형 규칙 또는 오른쪽-왼쪽 규칙이라고 부르기도 합니다.
C가 이 C로 간단한 을 쓸 수 합니다.int *p
C++에서는 구문이 조금 복잡해졌습니다(클래스, 참조, 템플릿, 열거 클래스 포함).이 복잡함에 대한 대응으로서 많은 선언에서 타입과 식별자를 분리하는 데 더 많은 노력을 기울일 것입니다. 더 볼 수 거예요.int* pC++ 코드의 큰 스윗을 체크하는 경우는, -style 선언을 실시합니다.
두 언어 모두 (1) 같은 문장에서 여러 변수를 선언하지 않고 (2) 다음을 사용함으로써 변수 선언의 왼쪽에 항상 유형을 가질 수 있다.typedefs(또는 에일리어스 선언, 아이러니컬하게도 에일리어스 식별자는 타입의 왼쪽에 배치됩니다).예를 들어 다음과 같습니다.
typedef int array_of_10_ints[10];
array_of_10_ints a;
이 토픽의 많은 논거는 주관적이고 "별이 변수 이름에 묶인다"는 주장은 순진합니다.여기 단순한 의견이 아닌 몇 가지 주장이 있습니다.
잊어버린 포인터 유형 한정자
형식적으로 "별"은 유형이나 변수 이름에 속하지 않으며 포인터라는 이름의 자체 문법 항목의 일부입니다.정식 C 구문(ISO 9899:2018)은 다음과 같습니다.
(6.7) 선언:
" " "init-interminator-listinit-interminator-list;
여기서 declaration-specificers에는 유형(및 스토리지)이 포함되어 init-declarator-list에는 포인터와 변수 이름이 포함됩니다.이 선언자 목록 구문을 더 자세히 분석하면 알 수 있습니다.
(6.7.6) 선언자:
포인터opt 다이렉트 액셀러레이터
(6.7.6) 포인터:
*(type-syslog-list)
*(type-syslog-list)
여기서 선언자는 선언 전체이며 직접 선언자는 식별자(변수 이름)이며, 포인터는 스타 뒤에 포인터 자체에 속하는 선택적 유형 한정자 목록이 이어집니다.
"별이 변수에 속함"에 대한 다양한 스타일의 주장이 일관되지 않는 이유는 이러한 포인터 유형 한정자를 잊어버렸기 때문입니다. int* const x,int *const x ★★★★★★★★★★★★★★★★★」int*const x
int *const a, b;, 「 「 」의 a ★★★★★★★★★★★★★★★★★」b"별은 변수에 속한다"는 것은 이제 명백하지 않다.서'가 나올까, '어디서'가 나올까 .const을 사용하다
별은 포인터 타입 한정자에 속하지만 그 이상은 아니라고 확실히 주장할 수 있습니다.
는, 수 .int *a 문체 . 포인터를 사용하는 사람들은typedef는 안 되는, 매우 "변수 이름에 하는 것은 버그를 이 있다: (별은 변수 이름에 속한다!)라고 생각하고, 「별은 변수명에 속한다」라고 하는 것은, 매우 미묘한 버그를 쓰는 경향이 있습니다.
/*** bad code, don't do this ***/
typedef int *bad_idea_t;
...
void func (const bad_idea_t *foo);
이것은 깔끔하게 편집된다.코드가 항상 올바르다고 생각하실 수도 있습니다.그렇지 않아!이 코드는 실수로 가짜로 정확한 코드입니다.
의 foo는 ★★★★int*const* 는 데이터를 것이 읽기 있습니다 - 이 포인터는 데이터를 가리키는 것이 아닙니다. 이 할 수 있어요.**foo = n;이치
는요, 이 은 '아까부터' 입니다.const bad_idea_t *foo , . . . . . . . .*!!서!!!!!에서는, 이은, 「이러다」라고 읽혀집니다.const (bad_idea_t *) foo로서가 아니라(const bad_idea_t) *foo. 이 , 이며, 로됩니다. 상수 수식 포인터는 상수 수식 포인터이다.*const.
를 포인터 뒤에 입니다.typedef가 and the *stylecontraction을 합니다.
한 줄에 여러 변수를 선언하는 것에 대하여
한 줄에 여러 변수를 선언하는 것은 잘못된1) 관행으로 널리 알려져 있습니다.CERT-C는 다음과 같이 요약합니다.
DCL04-C선언당 변수를 두 개 이상 선언하지 마십시오.
영어를 읽는 것만으로도 선언은 하나의 선언이어야 한다는 데 상식이 일치한다.
변수가 포인터인지 아닌지는 중요하지 않습니다.각 변수를 한 줄에 선언하면 거의 모든 경우에 코드가 명확해집니다.
것에 int* a, b 개 사용하는 이지, 선언자를 여러 개 하는 것이 .* 스타일에 대신 스타일에 관계없이 다음 내용을 작성해야 합니다.
int* a; // or int *a
int b;
하나의 으로, 것이다.int* a의 of의 a할 여지가 없다int*스타는 유형 한정자에 속합니다.
하지만 기본적으로 제 결론은 여기에 게시된 많은 주장들이 단지 주관적이고 순진하다는 것입니다.당신은 어느 스타일에도 타당한 주장을 할 수 없다 - 그것은 정말로 주관적인 개인적 선호의 문제이다.
1) CERT-C DCL04-C.
위대한 권위자가 말했다. "편찬자의 방식으로 읽으라, 그래야 한다."
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
이것이 항상 배치에 관한 것이었지만, 같은 규칙이 여기에 적용됩니다.
컴파일러는 다음과 같이 읽습니다.
int (*a);
다른 이름:
(int*) a;
변수 옆에 별을 붙이는 습관을 들이면 선언문을 읽기 쉬워집니다.또, 다음과 같은 눈에 거슬리는 일도 회피합니다.
int* a[10];
--편집 --
내가 말하는 의미를 정확히 설명하자면int (*a)즉,*보다 단단하게 결합하다a에 비해int표현에서와 같이4 + 3 * 7 3보다 단단하게 결합하다7에 비해4우선도가 높기 때문에*.
A.S.T.의 해석 개요인 아스키 아트에 대해 사과드립니다.int *a대략 다음과 같습니다.
Declaration
/ \
/ \
Declaration- Init-
Secifiers Declarator-
| List
| |
| ...
"int" |
Declarator
/ \
/ ...
Pointer \
| Identifier
| |
"*" |
"a"
분명히 나타나 있듯이*보다 단단하게 결합하다a그들의 공통 조상이니까Declarator트리를 끝까지 올라가야 하는데Declaration공통의 조상을 발견하다int.
이 행의 *는 유형보다 변수에 더 밀접하게 결합되기 때문입니다.
int* varA, varB; // This is misleading
@Lundin이 아래에 지적한 바와 같이 const는 더 고려해야 할 세부사항을 추가합니다.한 줄에 1개의 변수를 선언함으로써 이 문제를 완전히 회피할 수 있습니다.이것은 결코 애매하지 않습니다.
int* varA;
int varB;
클리어 코드와 간결한 코드의 밸런스를 맞추기는 어렵습니다.수십 줄의 장황한 코드와int a;그것도 좋지 않아요.그러나 기본적으로는 한 줄에 하나의 선언이 있기 때문에 나중에 코드 조합이 걱정됩니다.
이 질문에는 변수 선언과 파라미터 및 반환 유형 모두에 대해 명확한 답변이 있습니다.즉, 아스타리스크는 이름 옆에 붙어야 합니다.int *myVariable;이유를 이해하려면 C에서 다른 유형의 기호를 선언하는 방법을 확인하십시오.
int my_function(int arg);함수의 경우
float my_array[3]어레이의 경우.
일반적인 패턴은 다음과 같습니다.기호의 유형은 이름 앞부분과 이름 주변부분으로 분할되며, 이름 주변부분은 왼쪽에 있는 유형의 값을 얻기 위해 사용하는 구문을 모방합니다.
int a_return_value = my_function(729);
float an_element = my_array[2];
또, 다음과 같이 합니다.int copy_of_value = *myVariable;.
C++는 참조를 사용하는 시점의 구문이 값 유형의 구문과 동일하기 때문에 C++는 C에 대해 다른 접근방식을 취한다고 주장할 수 있습니다.한편, C++는 포인터의 경우 C와 같은 동작을 유지하므로, 이 점에 있어서 참조는 홀수로서 유효합니다.
왜냐하면 다음과 같은 선언이 있을 때 더 말이 되기 때문입니다.
int *a, *b;
그건 그냥 취향의 문제예요.
코드를 읽을 때 변수와 포인터를 구별하는 것이 두 번째 경우 더 쉽지만 공통 유형의 변수와 포인터를 모두 한 줄에 넣을 경우 혼란이 발생할 수 있습니다(프로젝트 가이드라인에 따라 가독성이 떨어지기 때문에 종종 이러한 변수와 포인터를 사용하지 않습니다).
예를 들어, 예를 들어 유형 이름 옆에 대응하는 기호가 있는 포인터를 선언하는 것을 선호합니다.
int* pMyPointer;
한 줄에 여러 포인터를 선언할 경우int* a, * b;이것은 정수에 대한 포인터로서 "a"를 보다 직관적으로 선언하고 마찬가지로 "b"를 선언할 때 스타일을 섞지 않습니다.누군가 말했듯이, 같은 문장에서 두 가지 다른 유형을 선언하지는 않을 것입니다.
예를 들어, 하나의 문에서 변수를 초기화하고 할당하는 경우.
int *a = xyz;
가치를 할당하다xyz로.a~하지 않다*a이렇게 하면
int* a = xyz;
보다 일관된 표기법
언급URL : https://stackoverflow.com/questions/398395/why-is-the-asterisk-before-the-variable-name-rather-than-after-the-type
'programing' 카테고리의 다른 글
| Vue에서 여러 구성 요소를 렌더링할 수 없음 (0) | 2022.08.22 |
|---|---|
| 이름 선행 HTML 요소의 Vue 오류 "알 수 없는 사용자 지정 요소"를 방지하는 방법 (0) | 2022.08.22 |
| VUE/VUEX: 부모 템플릿에서 자식 템플릿으로 데이터를 전달하는 방법 (0) | 2022.08.22 |
| vuex에서 vuex-module-decorator를 사용하여 서브모듈을 작성하려면 어떻게 해야 합니까? (0) | 2022.08.22 |
| v-model 값이 변경될 때 사용자 지정 Vue 선택 구성 요소가 선택한 옵션을 업데이트하지 않음 (0) | 2022.08.22 |