programing

포인터 유형을 선언하시겠습니까?

muds 2023. 6. 15. 22:08
반응형

포인터 유형을 선언하시겠습니까?

방금 읽은 바로는 C(또는 C++)로 선언하면서 포인터 유형을 지정해야 합니다. 예를 들어:

int *point ;

제가 알기로는 포인터는 변수의 주소를 저장하고 주소는 어떤 유형이든 동일한 양의 메모리를 차지합니다.그렇다면, 왜 우리는 그것의 종류를 선언해야 할까요?

형식 안전.만약 당신이 그것을 모른다면.p지적해야 할 것이 있다면, 다음과 같은 범주 오류를 방지할 수 있는 것은 아무것도 없을 것입니다.

*p = "Nonsense";
int i = *p;

정적 유형 검사는 그러한 모든 종류의 오류를 방지하는 매우 강력한 도구입니다.

C와 C++는 또한 포인터 산술을 지원하며, 이는 대상 유형의 크기가 알려진 경우에만 작동합니다.

주소는 내가 어떤 유형이든 동일한 양의 메모리를 차지합니다.

이는 오늘날의 인기 플랫폼에서도 마찬가지입니다.하지만 그렇지 않은 플랫폼들이 있었습니다.예를 들어, 다중 바이트 단어에 대한 포인터는 단어 내에서 바이트의 오프셋을 나타낼 필요가 없으므로 단일 바이트에 대한 포인터보다 작을 수 있습니다.

이유:

  1. 서로 다른 유형의 주소는 같은 크기일 필요가 없습니다.표준은 명시적으로 그렇게 명시하고 있습니다(C 2011 표준(온라인 초안), 6.2.5/28).
  2. type-safety: 컴파일러는 사용자가 함수 또는 할당에 호환되지 않는 포인터를 제공할 때 탐지할 수 있습니다.이렇게 하면 인수 순서를 함수로 엉망으로 만드는 추악한 상황을 방지할 수 있습니다.
  3. 컴파일러는 포인터가 참조되지 않을 때 유형을 알아야 합니다.
  4. 포인터 산술을 하려면 가리킨 개체의 크기를 알아야 하며 따라서 개체의 유형을 알아야 합니다.

두마막두점에않적습다니지되용은지▁▁to다않▁▁applyt'습▁points▁lastvoid포인터, 즉 포인터를 참조하지 않고 포인터 산술을 수행할 수 없는 이유입니다.표준은 다음을 명시합니다.void는 모든 전체적으로포인터 와그할 수 만큼 커야 .void포인터는 캐스트 없이 만들어질 수 있습니다(적어도 C에서, C++ 캐스트는 항상 필요합니다).

한 가지 이유는 포인터 산술에 있습니다.은 할 수 .p+1당신이 그 요소의 크기를 알지 못하는 한.p점 - 이것이 대상 유형의 크기입니다.p포인터입니다.당신이 해본다면요p+1에서.void *p당신은 나쁜 대답을 받을 가능성이 있습니다 (그것은 마치 a에서 한 것과 같습니다).char *하지만 아마도 당신은 그것을 원하지 않았을 것입니다; 그것은 잡혔습니다.-pedantic경고로서 그리고 그에 의해-pedantic-errors실수로).

또 다른 이유는 형식 안전입니다.에는 다음과 같이 합니다.int *은 에포를전수없다니습에 를 할 수 .char거기에 줄)경고(에 대한 오류)가 표시됩니다.-Werror/-pedantic-errors 코드를 이 (더미) 코드를 고려합니다.

void test(int *x)
{
}

int main()
{
    char *x = "xyz";
    test(x);
    return 0;
}

컴사일(용파) 사용)gcc (GCC) 4.8.2 20131017 (Red Hat 4.8.2-1)) 다음을 제공:

1.c: In function ‘main’:
1.c:8:2: warning: passing argument 1 of ‘test’ from incompatible pointer type [enabled by default]
  test(x);
  ^
1.c:1:6: note: expected ‘int *’ but argument is of type ‘char *’
 void test(int *x)
      ^

그렇다면, 왜 우리는 그것의 종류를 선언해야 할까요?

정적 유형 검사를 수행할 수 있도록 포인터의 유형을 알고자 합니다.

또한 포인터 산술이 작동하려면 유형을 알아야 합니다. 예를 들어 크기가 다른 배열(포인터 산술과 동일)로 인덱싱할 때 포인터는 유형 종속량에 의해 조정됩니다.초안 C99 표준 섹션을 살펴보면,6.5.6 가법 연산자는 다음과 같이 말합니다(내 것 강조).

또한 두 피연산자 모두 산술 유형을 가져야 하며, 하나의 피연산자는 객체 유형에 대한 포인터여야 합니다 [...].

따라서 포인터는 개체 유형이어야 하며, 이는 불완전하거나 비어 있지 않다는 것을 의미합니다.

당신은 또한 말했습니다:

주소는 유형에 관계없이 동일한 양의 메모리를 사용합니다.그렇다면, 왜 우리는 그것의 종류를 선언해야 할까요?

C++에서는 멤버 함수에 대한 포인터의 크기가 클래스 유형에 따라 달라질 수 있지만, 이를 다루는 좋은 기사 중 하나는 멤버 함수에 대한 포인터가 매우 이상한 동물이라는 입니다.

또한 C99 초안 표준 섹션 모두를 확인할 수 있습니다.6.2.5 다음과 같은 27항을 입력합니다.

[...] 다른 유형에 대한 포인터가 동일한 표현 또는 정렬 요구 사항을 가질 필요는 없습니다.

C 섹션 C++.3.9.2 제3항의 복합 유형은 다음과 같습니다.

[...] 포인터 유형의 값 표현은 구현 정의되어 있습니다.레이아웃 호환 유형의 cv-qualified 및 cv-qualified 버전(3.9.3)에 대한 포인터는 동일한 값 표현 및 정렬 요구사항(3.11)을 가져야 합니다. [...]

특정한 경우를 제외하고는 포인터가 동일한 표현을 가질 필요가 없습니다.

표준이 요구하는 대로 유형을 지정해야 합니다.또한 덧셈이나 뺄셈과 같은 포인터 연산을 시도할 때 문제가 없도록 합니다.

프로세서가 "주소에서 바이트 로드", "주소에서 16비트 하프워드 로드", "주소에서 32비트 워드 로드"에 대한 명령어가 서로 다른 반면, "저장" 작업의 경우에도 마찬가지로 C는 다른 크기 값을 로드하는 것과 동일한 구문을 사용하여 주소에서 바이트를 로드합니다.다음과 같은 문구:

int n = *p;

컴파일러는 p의 주소에서 바이트, 하프워드 또는 워드를 로드하여 n으로 저장하는 코드를 생성할 수 있습니다. p가 *인 경우, c의 부동소수점 값을 로드하고, 잘라내고, int로 변환하고, 변환된 값을 n으로 저장하는 더 복잡한 코드 시퀀스를 생성할 수 있습니다.p의 종류를 모르면 컴파일러는 어떤 작업이 적합한지 알 수 없습니다.

마가지로, 그진은술라는 p++를 늘수있다니습릴소▁▁the▁▁increase▁may다로 주소를 늘릴 수 있습니다.p하나, 둘, 넷 또는 다른 숫자로.주소가 증가하는 양은 선언된 p 유형에 따라 달라집니다.컴파일러가 p의 유형을 모르면 주소를 조정하는 방법을 알 수 없습니다.

포인터가 가리키는 대상의 유형을 지정하지 않고 포인터를 선언할 수 있습니다.이러한 포인터의 유형은 다음과 같습니다.void*은 야합다니해환을 .void*그러나, 그것으로 유용한 것을 하기 전에 실제 포인터 유형으로; 주요 유용성.void*는 포인터가 포터가로변경있환우로 .void*그것은 로서 회람될 수 있습니다.void*포인터의 실제 유형에 대해 아무것도 모르는 코드에 의해.만약 포인터가 결국 그것의 유형을 아는 코드에 주어지고, 그 코드가 포인터를 그 유형으로 다시 던지면, 그 결과는 변환된 포인터와 같을 것입니다.void*.

아무것도 는 종종 할 수 .void*그러나 포인터 포인트가 일반적으로 적절한 유형의 포인터를 선언해야 하는 것들에 대해 알고 있는 코드.

포인터 유형은 참조 해제 및 포인터 산술 중에 재생됩니다.예를들면

int x=10;     //Lets suppose the address of x=100
int *ptr=&x;   //ptr has value 100
printf("The value of x is %d", *ptr);
ptr++;  // ptr has value 104(if int is 4bytes)

위의 예에서 포인터 유형은 int이므로 컴파일러는 메모리 주소 100에서 시작하여 다음 4바이트(int가 4바이트인 경우)에 저장된 값을 찾기 시작합니다.그래서 포인터의 유형은 컴파일러에게 참조 해제 중에 몇 바이트를 찾아야 하는지 알려줍니다.포인터 유형이 없었다면 컴파일러는 참조를 취소하는 동안 표시할 바이트 수를 어떻게 알았을까요?그리고 우리가 ptr++을 했을 때 포인터의 종류는 ptr을 얼마나 증가시켜야 하는지에 따라 알려줍니다.여기서 reptr은 4씩 증가합니다.

char c='a';   //Lets suppose the address of c = 200
char* ptr=&c;   //ptr has value 200
ptr++;   //ptr has value 201(char assumed to be 1 byte) 

포인터 유형은 ptr이 1바이트씩 증가함을 나타냅니다.

그래서 그것은 산술과 다른 연산을 수행할 수 있습니다.다음 두 가지 예를 생각해 보십시오.

int* p; /* let the address of the memory location p pointing to be 1000*/
p++;
printf("%u",p); /* prints 1004 since it is an integer pointer*/


char *p; /* let the address of the memory location p pointing to be 1000*/
p++;
printf("%u",p); /* prints 1001 since it is an char pointer*/

이것이 당신에게 도움이 되길 바랍니다!

실제로 유형을 선언하는 데 필요한 것은 아니지만(아래 참조) 그래야 합니다.포인터는 개체 위치에 대한 정보를 저장하고 유형은 메모리에 필요한 공간을 정의합니다.

, - 를 사용하여 하는 등 합니다.new.

할 수 것은 그나여수 다있니입니다.void포인터, (어떤 이유로든) 유형을 숨기려는 경우:

void* dontKnowWhatTypeIsHere;

빈 포인터는 범용 포인터로 간주됩니다.이것은 어떤 물체든 가리킬 수 있고, 우리가 그것을 유형과 함께 사용하고 싶을 때, 우리는 그냥.reinterpret_cast.

앞서 말한 많은 진술들이 있지만 팬은 순전히 옳습니다.이제 우리가 포인터의 유형을 정의하는지에 대한 질문이 있습니까?포인터의 첫 번째 정의 다른 변수의 주소를 보유할 수 있는 포인터입니다.위의 정의는 부분적입니다.정확한 정의는 포인터는 변수의 주소를 보유할 수 있는 변수이며, 우리가 참조를 해제하면(값을 가져오면) 해당 주소의 현재 값을 반환합니다.포인터가 참조 해제 시 값을 반환하지 못하면 포인터가 아닙니다.gcc 컴파일러에서도 간단한 변수가 다른 변수의 주소를 유지할 수 있지만 참조를 해제하면 오류가 발생합니다.이제 데이터 유형에 관계없이 포인터의 크기는 항상 특정 컴파일러의 정수 크기와 동일합니다.따라서 gcc 컴파일러의 포인터 크기는 4바이트(정수 크기)이고 터보치의 포인터 크기는 2바이트(정수 크기)입니다.이제 왜 정수의 크기와 같은지에 대한 질문이 있습니다.int, char, float 등이 될 수 있는 변수의 주소는 항상 정수이고 정수가 int에 저장되는 주소입니다.포인터가 항상 순수 정수 데이터인 주소도 저장하기 때문에 포인터의 크기가 int의 크기와 같은 이유입니다.그렇다면 다른 데이터 형식 포인터의 int와 char의 차이점은 무엇입니까?검색 시 컴파일러가 데이터 유형에 따라 바이트 수를 가져올 것입니다. 그렇지 않으면 오류가 발생하거나 오류가 발생하지 않지만 예측할 수 없는 결과가 발생하지만 저는 그렇지 않습니다.포인터 데이터 유형에 따라 포인터의 증분 및 감소에도 동일한 규칙이 적용됩니다.포인터의 크기는 데이터 유형에 의존하지 않으며, 따라서 링크 목록이 나타나는 이유는 만약 당신이 같은 변수 안의 구조를 선언하려고 한다면 당신의 컴파일러가 완전한 선언 이전의 구조의 크기가 아니라 동일한 구조의 자체 참조 포인터가 크기 때문에 컴파일 시간 오류가 발생할 것이기 때문입니다.허용된 이유는?포인터의 크기가 데이터 유형의 크기에 의존하지 않기 때문에 유일한 대답입니다.문의 사항이 있으시면 저에게 물어보세요.감사합니다.

언급URL : https://stackoverflow.com/questions/20407747/declaring-type-of-pointers

반응형