# 002 DS&A-C 섹션의 포인터

소개


너 말고는 할 말이 없어.👋,
현수막에 있는 이 사람이 누군지 알고 싶다면 알고리즘 개념의 발명자인 Khwarizmi다.
반드시 따라주십시오. 왜냐하면 저는 미래에 더욱 고급스러운 시리즈를 시작할 것입니다.

포인터


포인터 소개


c 프로그래밍 언어에서 메모리를 1D 그룹으로 시각화합니다.

내가 a를 불렀을 때, 나는 실제로 감방 안에 있었다.
현재 a는 몇 개의 세포를 소모합니까?이것은 실시 상황에 달려 있을 것이다.많은 사람들이char는 항상 1바이트, int는 2바이트, 롱은 4바이트라고 생각하지만, 이것은 이렇게 고정된 것이 아니다.
프로그램이 실행되는 플랫폼에 따라 변수마다 일정한 크기가 있다.그러나 치수가 결정되면 고정됩니다.하지만 당신은 char가 모든 플랫폼에서 똑같다는 것을 수정할 수 없습니다. 이것은 사실이 아닙니다.
대부분의 시스템은 문자를 1바이트로 변환했다.이 플랫폼에서 int가 두 바이트를 차지할 것이라고 가정합시다.

다른 방법은 주소를 사용하여 접근하는 것입니다. 따라서 일부 메모리에 부여된 실체마다 주소가 있습니다. 때때로 변수에 접근해야 한다면 주소를 사용해서 접근할 수 있습니다. 이름을 완전히 잊어버릴 수도 있습니다.설령 우리가 이름이 있다 하더라도 주소를 사용하여 방문하는 것이 더욱 빠를 것이다.이름에 따라 호출할 때마다 논리적 주소로 변환되고 물리적 주소로 변환되기 때문에 어떤 방식으로든 요소에 접근해야 합니다.따라서 이름이 아닌 주소를 사용하는 것이 편리할 때가 있다.만약 우리가 이 이름을 사용한다면, 우리는 (인간으로서) 더 빨리 읽을 수 있지만, 기계 주소로는 더욱 쉽게 실현될 것이다.
바늘이 그림에 나타납니다. 바늘은 보통 주소를 처리합니다. 어떤 프로그램이나 바늘이 있는 실체를 작성할 때, 바늘이 없는 프로그램보다 더 빨리 실행되어야 합니다.이것은 첫 번째 장점이고, 또 다른 장점은 동적으로 만들어진 데이터 구조는 만들 때 이름을 바꿀 수 없기 때문에 이런 상황에서 그것들을 방문하는 유일한 방법은 주소를 통과하는 것이다.따라서 포인터는 C 프로그래밍 언어에서 중요한 역할을 발휘할 것이다.
우리 지침을 이야기합시다.무엇이 지침입니까?포인터는 다른 변수나 다른 실체의 주소를 포함해야 하는 변수입니다.모든 시스템에는 주소 찾기 메모리가 있는데, 바늘은 그 수량의 위치를 포함해야 한다.바늘의 크기는 플랫폼에 달려 있고, 어떤 플랫폼은 16위, 어떤 플랫폼은 32위이다.
char a;
int b;
int *p; //can be read as *p is a variable of type int .
p = &b; 
우리는 두 개의 연산자 1is=와 다른 is&가 있습니다. 첫 번째 연산자에서 보듯이 이 연산자는 b의 주소를 가져오는 데 사용됩니다. 변수의 주소나 다른 데이터 구조의 주소를 얻을 수 있습니다. 이 데이터 구조는 메모리에서만 설명됩니다.예를 들어, 표현식이나 상수의 주소를 가져올 수 없습니다.
이 플랫폼의 주소가 8비트=1바이트라고 가정하면 바늘은 1바이트만 필요합니다.

가령 b의 시작 주소가 100이라고 가정하면 b가 2바이트일지라도 p는 1바이트일 수 있다. 왜냐하면 이것은 주소를 가리키기 때문에 & b가 100이라면 p의 값은 100이다.크기가 int나char 또는 다른 구조라도 바늘의 크기는 항상 같습니다.
우리는 크기가 다른 집이 있지만, 집마다 같은 주소가 있다.
따라서 데이터 구조가 무엇이든지 주소는 항상 같고 바늘의 크기와 요소의 크기를 연결해서는 안 된다는 것을 기억하십시오.
그러나 크기가 중요하지 않다면, 왜 나는 int*p를 사용하고, 나는 예시를 통해char를 사용할 수 없다고 생각할 수 있습니까?이것은 사실이지만, 주소 알고리즘이라는 문제는 잠시 후에 토론할 것이다.
지금 만약 내가 p를 사용한다면, 마치 내가 100에 서 있는 것처럼, 만약 내가 주소 내부에 접근해야 한다면, 나는 *p를 사용해야 한다. 이곳은 차분 또는 간접 조작이라고 불린다.
& : address
* : dereferencing and indirection

만약 내가 단독으로 p(또는 b)를 사용한다면 나는 보라색 사람이 될 것이다. 만약 내가 별(또는 b)을 사용한다면 나는 그 안에 있을 것이다.
현재, p와 b는 같다.

예제


#include <stdio.h>

int main()
{
    int  x =  5;
    int *y = &x; // assume address of x is 0x7ffe5b67bf54

    printf("%d\n" ,  x); // output : 5
    printf("%p\n" , &x); // output : 0x7ffe5b67bf54
    printf("%p\n" ,  y); // output : 0x7ffe5b67bf54
    printf("%d\n" , *y); // output : 5
    printf("%p\n" , &y); // output : 0x7ffe5b67bf54

    return 0;
}
또 다른 예시이지만 기능이 있다
void f(int *p , int *q)
{
    p  = q;
    *p = 2;
}
int i = 0 , j = 1;

int main() {
    f(&i , &j);
    printf("%d %d\n",i,j);
    return 0;
}

이것은 함수가 실행되기 전의 가시화입니다.p는 i를 가리키고 q는 j를 가리킨다

실행 후 둘 다 (&j) 를 가리키고 프로그램은 0 2를 인쇄합니다

포인터 및 함수


void swap(int x , int y) {
    int temp;
    temp = x;
    x    = y;
    y    = temp;
}

int main() {
    int a,b;
    a = 3;
    b = 4;
    swap(a,b);

    return 0;
}
main 함수에서, 우리는 a와 b를 가지고 있으며, 그것들은main의 창고에 있을 것이다

내가 그것들을 값에 따라 함수에 전달할 때, 함수에 새 창고를 만들 것이다

이곳의 x와 y는 a와 b와 다르다. 왜냐하면 그들은 a와 b의 값만 취하고 주소를 찾지 않기 때문에 메모리에서 서로 다른 주소를 차지한다.따라서 x나 y에 대한 어떠한 변경도 a와 b에 영향을 주지 않는다.
지금 이 버전을 보여드릴게요.
void swap(int *x , int *y) {
    int temp;
    temp = *x;     // temp = 3
    *x   = *y;    // *x=a=4
    *y   = temp; // *y=b=temp=3
}

int main() {
    int a,b;
    a = 3;
    b = 4;
    swap(&a,&b); // assume &a=100 and &b=200

    return 0;
}

현재 x의 값은 주소'a'이고 y의 값은 주소'b'이기 때문에 x는'a'이고 y는'b'입니다.X와 Y의 주소는 여전히 a와 b와 다르지만, X와 Y의 값은'a'와'b'의 주소입니다.
따라서 제가 *x에 대한 모든 변경은'a'에 영향을 줄 수 있습니다. 왜냐하면 제가 여기서 주소를 수정했기 때문입니다. *y에도 마찬가지입니다.
이것은 함수에서 a와 b에 접근하는 방법이다.

포인터 및 배열


수조와 바늘은 어떤 의미에서 밀접한 관계를 가진다. 수조와 접두사로 무엇을 하든지 바늘로 할 수 있다.
만약에 우리가 [5]를 가지고 있다고 가정하면 이것은 우리가 5개의 int 요소를 가지고 있기 때문에 5개의 연속적인 메모리 공간을 분배할 것이다. 만약에 우리의 블록이 100에서 시작되면 시스템에서 모든 정수가 2개의 바이트를 차지하고 시스템은 바이트가 주소를 찾을 수 있다. 이것은 바이트마다 다른 주소를 얻을 수 있다는 것을 의미한다. 일반적인 시스템은 글자가 주소를 찾을 수 있고 이것은 한 글자가 유일한 주소를 얻을 수 있다는 것을 의미한다.따라서 단어가 2바이트라면 2바이트마다 유일한 주소가 있다는 것을 의미한다.그러나 우리는 그것이 바이트라고 가정하기 때문에 모든 바이트는 유일한 주소를 얻을 수 있다.
따라서 스토리지에 10바이트(2*5)

그룹 이름은 변수가 아니라 주소를 나타내는 다른 방식일 뿐이다.그래서 메모리에 어떤 이름도 분배되지 않습니다.하지만 [0]a[1]...그것들은 분배될 것이지만 it 자체가 아니다.a는 마치 100의 세포 밖에 서 있는 것과 같다. *a는 네가 세포 안으로 들어가는 것을 의미한다. 그래서 *a=a[0], 지금 내가 들어가야 한다면[1].
현재 우리는 *(a+2)=a[1]에서 이것은 잘못된 것이라고 생각한다. 여기에 주소 산술이라는 것이 있을 것이다.주소 산술은 이렇게 작동하기 때문에 바늘의 임의의 수조 이름에 정수를 추가하려고 할 때마다 덧셈은 비례 덧셈입니다.
따라서'a'가 여기서 100을 대표한다면 a+1은 a의 다음 원소를 대표할 것이다. 그 중에서 102, a+2는 104이다. 그래서 내가 일반적인 a+I를 쓸 때 내부에서 a+(I*sizeof(int))로 전환한다. 그래서 나는 원소의 유형에 관심이 없다. 그래서 *(a+3)=a[3]를 입력할 때마다 내부에서 *(a+3)로 전환한다. a[3]는 인류 우호이고 *(a+3)는 기계 우호이다.그 밖에 (a+3)=&a[3]는 &(a[3])와 같을 필요가 없다. 왜냐하면 []의 표현 형식이 &보다 높기 때문이다.
하면, 만약, 만약...
int *p;
p = &a[0];  // p will point to address 100
p = p+1;    // p will point to address 102
p = p+1;    // p will point to address 104
컴파일러는 어떻게 알았습니까?이전에 우리가 말한 바늘마다 어떤 유형을 가리키기만 하면 고정된 크기가 있었다는 것을 기억하십니까?이것이 바로 내가 바늘 앞에 int를 입력할 때, 컴파일러가 지금 정확하게 그것을 증가시키는 이유이다.
p는 주소 100이 있기 때문에 p=p+3을 입력하면 106과 같고
*(p+3)=a[3]=p[3]
화목하다
p+3=a+3=&a[3]
하면, 만약, 만약...
a=a+1; // X
a++; // X
a=b; //X
이 모든 것은 허용되지 않습니다. 왜냐하면 a는 값이 아니기 때문입니다.그러나 다른 상황에서 이것들은 모두 유효하다
p=p+1;
p++;
p=variable;
p는 변수이기 때문에, 이것이 바로 수조와 바늘 사이의 차이이다
따라서 내가 함수에 수조의 이름을 전달할 때마다 시작 주소를 전달합니다. 이것은 우리가 호출한 함수에서 바늘을 가져옵니다. 이 바늘을 사용하면 수조에서 실행한 것과 같은 작업을 수행할 수 있습니다.

포인터 알고리즘 또는 주소 알고리즘


유효한 포인터 작업:
a) 동일한 유형의 포인터 값:
두 포인터가 같은 유형을 갖는 경우 다음과 같이 지정할 수 있습니다.
int *p,*q; // same type
p=q; // legal
q=p; // legal
int *p , a[];
p=a;// allowed
a=p;// Now allowed hince a is not an variable
만약 우리가 두 가지 다른 유형의 지침을 분배해야 한다면, 우리는 유형 전환을 해야 한다.우리는 모든 바늘에 같은 크기의 메모리가 있다고 말한다. 이것은 옳다. 우리는 그것들을 분배할 수 있지만, 산술 연산을 해야 할 때, 컴파일러는 곤혹스러울 것이다.
char *c;
int *p;
p = (int*)c;
항상 변환을 강제해야 하며, 이 포인터는 야생 포인터여야 합니다. (null로 초기화되지 않았더라도) 그렇지 않으면 허용되지 않습니다.
b) 정수 더하기 또는 빼기 포인터:

네가 튀어나오지 않으면, 너는 가감법 방면에 문제가 없을 것이다.너는 잘못을 하나 얻게 될 것이다.
c) 동일한 그룹 구성원을 가리키는 두 개의 포인터를 빼거나 비교합니다.

만약 우리가 두 개의 바늘이 같은 수조를 가리키고 있다면, 너는 그것들을 비교할 수 있다.그 밖에 너는 그것들을 줄일 수 있을 뿐, 너는 그것들을 이동하거나 추가로 추가할 수 없다.만약에 우리가 p와 q 사이의 원소수를 얻어야 한다고 가정하면 p와 q를 포함하여 나는 p와 q 사이에 q-p+1을 쓸 것이다. 만약에 모든 칸이 2바이트라면 p-q는 2로 나눌 것이다. 만약에 p는 102부터 시작하여 q는 106이기 때문에 p-q=4/2=2이기 때문에 q-p+1=2+1=3이다. 이것은 정확하다. 우리는 3개의 단원격이 있기 때문에 3개의 원소가 있다.
d) 값을 지정하거나 0보다 낮음
포인터를 0으로 지정할 수 있지만 의미가 없습니다.유일한 경우, 만약 우리가 바늘이 유효한지 확인해야 한다면, 우리는 보통 바늘이 0인지 아닌지를 확정할 것이다.

좋은 웹페이지 즐겨찾기