yeahzzz
archive
yeahzzz
전체 방문자
오늘
어제
  • 분류 전체보기 (164)
    • Language (41)
      • Python (12)
      • JAVA (21)
      • C&C++ (8)
    • Algorithms (25)
      • programmers (9)
      • study log (16)
    • Problems & Solutions (14)
    • Major (29)
      • Data Structure & Algorithm (14)
      • Linux(Ubuntu) (9)
      • Security (2)
      • Linear Algebra (4)
    • FE (44)
      • Web(HTML5, CSS, JS) (5)
      • React & TS (26)
      • 코딩일기 (10)
    • BE (1)
      • Node.js (1)
    • Pytorch (8)
    • Server (2)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
yeahzzz

archive

pointer
Language/C&C++

pointer

2021. 8. 5. 15:38

CPU는 메모리와 함께 작동.. 

메모리에서 데이터 가져오는 속도 >>>>>>.... >>>> 디스크에서 데이터 가져오는 속도 

디스크(보조 기억 장치) 에서 메모리로 필요한 데이터를 가져옴(메모리에 로딩 됨)

byte단위로 고유한 주소가 존재함. 따라서 CPU는 그 주소를 사용하여 데이터를 읽어옴

모든 데이터는 반드시 메모리에 존재하고 반드시 그 고유한 주소값이 있음. 

C언어(만) 그 메모리 주소를 직접적으로 다룰 수 있음..

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#pragma warning(disable:4996)
 
/**  포인터1 :
*    메모리
*        연속된 1byte 단위들의 공간
*        1 byte 단위로 데이터를 저장된다.
*        각 byte 데이터는 고유한 주소값을 통해 접근 가능
*        ex) int 값은 4byte 이므로 '연속된' 1byte x 4개 공간에 저장된다.
*
*    주소
*        : Windows 환경에선 주소는 4byte.  (Mac 이나 Linux 에선 8byte);
*
*    주소연산자 : &
*        변수가 저장된 주소값을 리턴하는 연산자
*        int 같이 여러byte 에 걸쳐 저장된 데이터의 경우 첫번째 byte 의 주소값
*
*    참조연산자 *
*       포인터를 사용해서, 담고 있는 주소값을 찾아가 그 주소 안의 '값'을 참조. (읽기, 쓰기)
**/
 
int main()
{
    printf("주소연산자 & \n");
 
    int n = 100;
 
    // 주소값 출력시는 %p ㅊㅊ;
    // 변수명 앞에 & 사용하면 변수의 주소값 반환
    // %p 로 출력시 16진수 8자리로 표현 (32bit, 4byte) ※ 16진수 2자리를 1byte 분량에 해당
    printf("n = %d, n 의 주소는 %d, %x, %p\n", n, &n, &n, &n);
    printf("sizeof(포인터) = %d\n", sizeof(&n));
 
    // 포인터 변수 선언.  '주소' 를 담는 변수
    int* p;  // int타입 포인터 변수 p 선언
            // p는 int타입 데이터가 저장되어 있는 주소를 담는다.
 
    p = &n;  // int 변수 n 의 '주소'를 포인터 p 에 대입
    printf("p = %p, &n = %p\n", p, &n);
 
    printf("참조연산자 * \n");
    // 포인터를 사용해서, 담고 있는 주소값을 찾아가 그 주소 안의 '값'을 참조. (읽기, 쓰기)
    printf("*p = %d\n", *p); // 참조 (읽기)
 
 
    *p = 500; // 참조 (쓰기)  p가 가리키는 주소의 값(int) 을 500으로 바꿈
 
    printf("n = %d, *p = %d\n", n, *p);
 
 
    int* p2;  // int 타입 포인터 p2 선언
    p2 = p;
    printf("p2 = %p, *p2 = %d\n", p2, *p2);  // 참조(읽기)
 
 
    // 주의!
    // 포인터에 직접 주소값을 대입하지 말자!
    p = 100;   // p에 100번지 주소값 대입?
    printf("*p = %d\n", *p);   // 접근하면 안되는 메모리 영역을 포인터러 접근하면 에러
 
 
    printf("\nENTER 를 누르면 종료됩니다\n");
    getchar();
    return 0;
}
 
Colored by Color Scripter
cs

각 칸마다 주소 지정. 

4byte를 담을 수 있는 적절한 공간이 생김. 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main() {
 
    int *numPtr;
    int num1 = 10;
 
    numPtr = &num1;
 
    printf("%p\n", numPtr);
    printf("%p", &num1);
 
 
    return 0;
}
cs

실행결과 같음. 

포인터 : C언어에서 메모리 주소는 포인터 변수에 저장

자료형*포인트이름;

포인터 = &변수;

 

 

포인터 연산

자료형에 따라서 증가하는 값이 다르다.

예) int : +1; 4바이트 증가

 

포인터 & 배열

배열의 이름은 포인터다!  포인터 '상수'
포인터 연산이 적용ㄱㄴ
배열첨자 연산자 []  <<< 결국 포인터 연산이다
arr[n] ↔ *(arr + n)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/** 포인터와 배열
*
*  배열의 이름은 포인터다!  포인터 '상수'다!
*    포인터 연산이 적용된다.
*
*    배열첨자 연산자 []  ← 결국 포인터 연산이다
*
*        arr[n] ↔ *(arr + n)   ★★★
*
**/
 
 
#include <stdio.h>
#pragma warning(disable : 4996)
 
int main() {
    //배열은 연속된 메모리 공간에 생성 
    int arr[3] = { 10,20,30 };
 
    //배열 이름은 곧 배열의 주소.
    //포인터와 같이(처럼) 동작함
    // arr의 포인터로서 타입 : int*
    //arr도 참조연산자 사용 가능함.( *arr)
 
    printf("arr = %p\n", arr);
 
    //*arr 
    //첫번째 값 산출됨. 
    printf("*arr = %d\n", arr);
    
    //포인터연산(+,-) 또한 쌉가넝  
    //얘도 뭐... 자료형에 따라서 달라지네. 
    printf("arr+0 = %p , *(arr+0) = %d\n", arr + 0, *(arr + 0));
    printf("arr+1 = %p , *(arr+1) = %d\n", arr + 1, *(arr + 1));
    printf("arr+2 = %p , *(arr+2) = %d\n", arr + 2, *(arr + 2));
 
    printf("arr[0] = %d , (arr+0) = %d\n", arr[0], *(arr + 0));
    printf("arr[1] = %d , (arr+1) = %d\n", arr[1], *(arr + 1));
    printf("arr[2] = %d , (arr+2) = %d\n", arr[2], *(arr + 2));
 
    // 다른 포인터 변수로 배열을 가리킬수 있다.
    int* p = arr;
    printf("\n");
    printf("p[0] = %d\n", p[0]);
    printf("p[1] = %d\n", p[1]);
    printf("p[2] = %d\n", p[2]);
 
    printf("-------------------------------\n");
    // 포인터 변수와 배열의 차이점
    printf("sizeof(p) = %d\n", sizeof(p));  // 4
    printf("sizeof(arr) = %d\n", sizeof(arr));  // 12
 
    printf("p = %p, &p = %p\n", p, &p);  // 다르다
   //arr은 어떠한 상수이기때문에 같게 나옴.
    printf("arr = %p, &arr = %p\n", arr, &arr);  // 같다
 
    int arr2[] = { 100, 200, 300 };
    p = arr2;
    //arr = arr2;  // 불가 arr은 상수다!
    //arr2 = p;    // 불가
 
    printf("-------------------------------\n");
    // 함수호출시 매개변수로 배열을 넘겨줄때는 배열이름(포인터) 전달.
    int total = calcTotal(arr, sizeof(arr) / sizeof(arr[0]));
    printf("총점은 = %d\n", total);
 
    getchar();
    return 0;
}
Colored by Color Scripter
cs

 

포인터를 포인팅하는 포인터도 있지 않을까?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#pragma warning(disable:4996)
 
int main() {
 
    int num1 = 10;
    int *p = NULL;
    //int형을 가리키기 위한 포인터 , 초기값 NULL(아무 주솟값도 없음)
    int **pp = NULL;
    //int형 포인터(int*) 를 가리키기 위한 포인터. = 2차원포인터 /이중포인터
 
    p = &num1;
    pp = &p; //포인터 p의 주소를 담은 pp 
 
    printf("%d %p %p\n", num1, p, pp);
 
    printf("%d %d %p %d\n", num1, *p, *pp, **pp);
 
    // p 의 타입은? --> int*
    // *p 의 타입은? --> int
 
    // pp 의 타입은? --> int**
    // *pp 의 타입은? --> int*
    // **pp 의 타입은? --> int
 
    //printf("%d\n", ***pp); // **pp 는 int다. 참조연산자 * 사용 불가
 
    printf("\nENTER 를 누르면 종료됩니다\n");
    getchar();
    return 0;
}
Colored by Color Scripter
cs

역참조 

포인터는 변수의 주소만 가리키지만

역참조 포인터는 그 값을 가져옴 

포인터를 선언할 때도 *를 사용하고 역참조를 할 때도 *를 사용합니다.

같은 * 기호를 사용해서 헷갈리기 쉽지만 선언과 사용을 구분해서 생각하면 됩니다. 즉, 포인터를 선언할 때 *는 "이 변수가 포인터다"라고 알려주는 역할이고, 포인터에 사용할 때 *는 "포인터의 메모리 주소를 역참조하겠다"라는 뜻입니다.

int *numPtr; // 포인터. 포인터를 선언할 때 *

printf("%d\n", *numPtr); // 역참조. 포인터에 사용할 때 *

 

역참조 연산자

값을 가져오기도 가능, 값을 저장하기도 가능.

자료형을 바꾸는 효과도 냄.

int *num/ 에서 *num처럼 역참조, 

pointer to int 에서 pointer to를 제거하여 int로 만듦. 

그냥 쉽게 생각하면 * 삭제해준다?라고 .. 그런 식으로 생각해도 ㄱㅊ을듯?

 

int *numPtr; int num1 = 10; numPtr = num1; // 컴파일 경고, numPtr은 int 포인터형이고 num1은 int형이라 자료형이 일치하지 않음 *numPtr = num1; // *numPtr은 int형이고 num1도 int형이라 자료형이 일치함

 

'Language > C&C++' 카테고리의 다른 글

swea1959  (0) 2021.11.01
C프 문자열 입력 받을 때 주의할 점.  (0) 2021.10.28
SWEA task code  (0) 2021.10.11
SWEA task code 0  (0) 2021.10.03
Lecture REVIEW 01  (0) 2021.07.20
    'Language/C&C++' 카테고리의 다른 글
    • C프 문자열 입력 받을 때 주의할 점.
    • SWEA task code
    • SWEA task code 0
    • Lecture REVIEW 01
    yeahzzz
    yeahzzz

    티스토리툴바