본문 바로가기

C언어/복습

[C언어]DAY8, 9_포인터, 배열이름의 의미와 인덱스 의미, 포인터와 배열이름

포인터, 메모리주소

- 메모리란 ? 저장공간

- 주소란 ? 메모리안에서 저장공간의 위치

- 변수란? 메모리안에서 할당된 저장공간. 값을 저장.1, 'a'

- 포인터란 ? 주소를 저장하는 변수

 

&: 어드레스 연산자(주소 연산자)
   변수앞에 붙이면 변수의 주소를 알아낼 수 있다.

* : 참조연산자
  변수에 담긴 주소에 있는 데이터(포인터가 가리키는 데이터)

 

#include int main()

{

      //변수 선언 (값을 저장하는 변수)

     int num1 = 10;

     int num2 = 20;

 

     //포인터 선언 (주소를 저장하는 변수)

     int * p_num = NULL; //0과 같은 포인터 변수의 디폴트 값

 

      p_num = &num1;

     //&num1: num1의주소를 p_num에 대입.

 

     //출력(변수에 들어있는 값을 읽기)

     printf("num1 = %d\n", num1);

     printf("num2 = %d\n", num2);

     printf("&num1 = %p\n", &num1);

     printf("p_num = %p\n", p_num); //0073FBB0

     //%p: 포인터를 위한 출력지정자. (16진수)

     //1byte =8bit =4bit(16) + 4bit

     //주소 = 4byte. =32bit운영체제용

     printf("*p_num = %d\n", *p_num);

     printf("sizeof num1 = %d\n", sizeof(num1));

     printf("sizeof p_num = %d\n", sizeof(p_num));

}

 


 

//목표: 포인터사용예.

//함수로 2개 이상의 값을 변경하고자 할 때

//한개만 변경하고자 할 때는 return으로 받으면 됨.

//swap(a,b) function을 만들기 : a에 b의 값을, b에 a의 값을 대입

 


#include <stdio.h> 

void swap(int *a, int* b)
{
	int temp=0;

	temp=*a;
	*a=*b;
	*b=temp; 
}

int main() 
{
	int a=10;
	int b=20;

	printf("a= %d b= %d \n", a,b ) ; 
	swap(&a,&b); 
	printf("a= %d b= %d \n", a,b ) ; 

}

 


// 목표 : 포인터사용예 #2
// 함수에서 배열을 넘기고자 할 때
// 배열을 다른 함수로 넘긴다고 가정해보자. arr[1,000,000]
// 만약에 데이터를 넘길때마다 복사를 한다면 속도, 메모리의 엄청남 성능 저하.
// 해결책 : 복사를 하지 말고 배열의 이름(=주소)만 넘기면 됨.
// 호출된 함수는 배열의 이름을 포인터로 받으면 해결.
// 호출된 함수는 배열이 넘어갈 때 배열의 사이즈를 알 수 있는 방법이 없으므로
// 반드시! 배열의 크기도 넘겨줘야 한다. parameter로 받는다는 의미.

 

 

#include <stdio.h>
#define SIZE 5

void print1(int * p_arr, int count){ // 스트링출력= 문자(아스키코드= 숫자 48 ~ 122)
	int i = 0;

	//출력#1
	for( i = 0; i < count; i++){
	printf("%c", p_arr[i]);
	}
	printf("\n");
}

void print2(int * arr, int count){
	int i = 0;

	//출력#2
	for( i = 0; i < count; i++){
		printf("%d\n", *(arr+i));
	}
	printf("\n");

}

void change_arr(int * arr, int count){
	int i =0;
	for( i = 0; i < count; i++){
	arr[i] += 100;
	printf("%d\n", *(arr+i));
	}
}

// 참조연산자 arr[i] = *(arr+i)
void change_arr2(int * arr, int count){
	int i =0;
	for( i = 0; i < count; i++){
	*(arr+i) += 100;
	}
}



int main(){
	int arr[SIZE] = {65, 66, 67, 68, 69}; //SIZE를 지정안하면 초기값개수만큼 배열의 크기가 정해짐.
	int arr2[3] = {70, 71, 72};
	int i = 0;
	print1(arr, SIZE);
	print1(arr2, 3);
	print2(arr, SIZE);

	//quiz : arr배열 각 원소에 100씩 더한 후, arr을 출력하세요. (print1()이나 print2()를 이용)
	change_arr(arr, SIZE);
}

배열이름의 의미와 인덱스 의미

[] 인덱스 연산자
배열을 참조연산자 *로 접근하는 방법
arr[i] = *(att+i) 중요!!

 

#include
#define SIZE 5
int main()
{

     int arr[SIZE] = {65,66,67,};
     int i=0;

 

     for(i=0; i printf("%d\n", arr[i]);{

          printf("%d\n", arr[i]);
     }
     printf("주소를 이용하여 출력\n");
     for(i=0; i <SIZE; i++){

          printf("%p %d\n", arr+i, *(arr+i));

          //1 =1byte가 아니고 1*sizeof(int).
         //int배열이므로. 배열의 원소가 int type이므로 
     }

 

     //배열의 크기
     printf("size of arr: %d\n", sizeof(arr[0]));
     printf("size of arr: %d\n", sizeof(arr));

 

     printf("arr = %p \n", arr);
     //배열의 이름은 배열이 시작되는 메모리의 주소이다.
     //%p :주소, 포인터를 나타내는 출력지정자.헥사값(16진수값)
}

 


// 목표 : 배열의 이름과 배열 인덱스의 의미
// int type으로 intArr[]를 선언하고 사용자로부터 5개의 정수를 입력받고 출력하되,
// 배열인덱스를 사용하지 말고 참조연산자 *만을 사용하라.
// 1.배열인덱스 사용해서 arr[i] arr은 주소, 주소는 포인터(주소를 담는 변수)에 담김.
// 2.참조연산자 사용해서 *(att+i)
//arr[i] = *(arr+i)

 

#include <stdio.h>
#define SIZE 5

void array_inout(){
	int arr[SIZE] = { 0, }; // 부족한 값은 0으로 채워서 초기화가 됨.
	int i = 0;
	printf("정수 %d개 입력하세요\n", SIZE);

	for( i=0; i<SIZE; i++) {
		scanf_s("%d", &arr[i]); //&arr[i] : 주소 &arr[i] = &num
	}

	printf("입력된 값은 : \n");
	for( i=0; i<SIZE; i++) {
		printf("%d  ", arr[i]); //&arr[i] : 주소 &arr[i] = &num
	}
	printf("\n");
}

//void pointer_inout(){
//
//	int arr[SIZE] = { 0, }; // 부족한 값은 0으로 채워서 초기화가 됨.
//	int i = 0;
//	printf("정수 %d개 입력하세요\n", SIZE);
//
//	for( i=0; i<SIZE; i++) {
//		scanf_s("%d", arr+i); //arr: 주소 arr+i = &arr[i]: 주소
//	}
//
//	printf("입력된 값은 : ");
//	for( i=0; i<SIZE; i++) {
//		printf("%d  ", *(arr+i)); //*arr : 값 arr[i] = *(arr+i) : 값
//	}
//	printf("\n");
//}

int main(){

	array_inout();
	//pointer_inout(); 

 


포인터와 배열이름

- 배열이름(상수)과 포인터(변수)는 완벽하게 똑같이 동작한다.
- 포인터(변수) = 배열이름(상수) **가장 중요함!!**
- a=1 printf("%d",a) printf("%d",1) 와 같은 원리 a = 변수, 1은 상수.
- a=1, b=2일 때 a=b:a라는 변수에 b에 담긴 값(2)가 대입
- lvalue : = 중심으로 왼쪽에 있는 값 (변수)
- rvalue : = 중심으로 오른쪽에 있는 값 (값) 배열이름 = 포인터

 

#include
#define SIZE 5

int main(){
     int arr[SIZE] = { 65, 66, 67, 68, 69}; //선언과 초기화 동시에.
     int i = 0;

//포인터 선언
     int * p_arr= arr; //선언과 초기화 동시에
     printf("%p %p\n", arr, p_arr);

 

//출력#1
     for( i = 0; i < SIZE; i++ ){
          printf("%d ", arr[i]); // arr은 상수이기때문에 arr++표현 쓸 수 없음, 3++
     }
     printf("\n");

 

//출력#2 arr[i] = *(arr+i)
     for( i = 0; i < SIZE; i++ ){
          printf("%d ", *(arr+i));
     }
     printf("\n%p\n", p_arr);

 

//출력#3 포인터
     for( i = 0; i < SIZE; i++ ){
          printf("%d %p\n", *(p_arr+i), p_arr);
     }
     printf("\n%p\n", p_arr);

 

//출력#4 포인터가 변수라는 점을 활용해서 ++표현
     for( i = 0; i < SIZE; i++ ){
          printf("%d %p\n", *(p_arr++),p_arr); //i++
     }

     printf("\n%p\n", p_arr);


//출력#5 포인터는 배열이름과 완벽하게 동일하게 작동한다는 점을 활용해서
     p_arr = arr;
     for( i = 0; i < SIZE; i++ ){
          printf("%d %p\n", p_arr[i], p_arr);
     }
     printf("\n%p\n", p_arr);
}