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;
}
|
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;
}
|
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;
}
|
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 |