Recent Posts
Recent Comments
Link
«   2025/07   »
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
Archives
관리 메뉴

OnlyOne

Memory&Pointer 본문

Control Engineering/C Programming

Memory&Pointer

Taesan Kim 2024. 9. 5. 00:12
본 포스팅은 한동대학교 21학번 과학기술전문사관 후보생 최윤석 선배님의 C언어 교육자료로 제작되었음을 알려드립니다. 감사합니다.

 

Memory&Pointer

 

Intro

이번 포스팅에서는 포인터와 배열을 메모리 관점에서 이해하고 메모리를 최적화하는 법에 대해 다룰 것이다.

 

메모리

예를 들어 32비트 컴퓨터는 2의 32승개의 메모리 용량을 지니며 약 4.3G 메모리를 갖고 있다.

위 그림에서 메모리 주소는 16진법이므로 b를 x로 고쳐준다.

 

메모리와 변수의 선언/할당

 

 

포인터

포인터란 메모리에 저장된 변수의 가장 낮은 주솟값이다.

아래 설명처럼 int는 4byte용량을 가지며, int의 명령어는 CPU로 하여금 임의로 4byte의 메모리를 할당하도록 한다. 이때 pointer은 변수가 저장된 가장 낮은 주소에 배치된다.

참고로, bit는 연산의 최소단위이고, byte는 메모리의 최소 단위이다. 

 

위 예시에서 num은 4byte의 용량을 가진다. CPU는 임의로 4byte를 할당한다. Pointer은 변수가 저장된 메모리의 가장 낮은 주소에 배치한다. 

#include <stdio.h>
int main()
{
 	int num = 10;
 	int* num_p = &num; //포인터 값에는 참조 연산자를 넣는다. 포인터에 절대 상수값을 넣지 않는다.
 	printf("Pointer: %p, Value: %d\n", num_p, *num_p);
 	return 0;
}

 

 

포인터와 배열

 

 

포인터의 연산

#include <stdio.h>

int main()
{
 	int array[5] = {1, 2, 3, 4, 5};
 	int* ptr1 = array; //4byte 단위로 연산
 	int* ptr2 = ptr1 + 1; //4byte만큼 주소 증가 = Array의 2번째 요소의 주소값
 	int* ptr3 = ptr1 + 2;
 	printf("Value: %d\n", *ptr2); //2
 	printf("Value: %d\n", *ptr3); //3
 	return 0;
}

 

int main()
{
 	int array[5] = {1, 2, 3, 4, 5};
 	int* ptr = array;
 	int num1 = *(ptr++); //1
 	int num2 = *(ptr++); //2
 	int num3 = *(--ptr); //2
 	return 0;
}

 

 

동적할당(배열과 포인터)

사용자가 런타임(Runtime)임의로 메모리를 할당하고 해제하는 방법

*런타임 : 프로그램 실행할때 검은색 창 뜰 때 할당 시작한다.

*정적 할당 : 컴파일때 할당, 컴파일타임 또는 빌드타임.

#include <stdlib.h>
int main()
{
 	int* array = (int*)malloc(sizeof(int) * 5);
 	array[0] = 0;
 	array[1] = 1;
 	array[2] = 2;
 	array[3] = 3;
 	array[4] = 4;
 	free(array); //동적할당에서는 free를 이용하여 반드시 할당된 메모리를 초기화해야 한다.(컴퓨터 느려짐.)
}

 

 

메모리 구조

 

 

 

구조체와 포인터

우리가 만든 Complex처럼 간단한 구조체도 있지만, 일반적으로 구조체는 그 크기가 매우 크다. 그래서 포인터 혹은 전역변수로 선언하는 경우가 많다.

#include <stdlib.h>
typedef struct _LIDAR
{
 	double angle[100];
 	double range[100]; //1600byte를 차지한다.
} LIDAR;
int main()
{
 	LIDAR* lidar_data = (LIDAR*)malloc(sizeof(LIDAR)); 
    //구조체의 주소만 저장하면 8byte로 구조체 불러올 수 있다.
 	...
 
 	free(lidar_data);
}

 

포인터 구조체의 멤버 접근은 2가지 방법이 있다. 다음과 같다.

#include <stdlib.h>
typedef struct _LIDAR
{
 	double angle[100];
 	double range[100];
} LIDAR;
int main()
{
 	LIDAR* lidar_data = (LIDAR*)malloc(sizeof(LIDAR));
 	lidar_data->angle; // 1. ->를 통해 접근
   	(*lidar_data).angle; // 2. 역참조 후 .을 통해 접근
    //angle배열의 첫번째 요소의 주소로 접근한다.
 	free(lidar_data);
}

 

 

함수와 포인터

함수의 내용은 기본적으로 코드에 저장되지만, 실제 사용될 때는 스택에 저장된다. 따라서 함수도 메모리에서 불러올 수 있고 이것은 함수도 포인터가 존재함을 의미한다.

 

#include <stdio.h>
void print_num(double num)
{
 	printf("%f\n", num);
}
int main()
{
 	void (*function_ptr)(double num);
    //함수 반환값, 함수 포인터 이름, 매개변수
 	function_ptr = print_num;
 	function_ptr(10.0);
}

함수도 변수처럼 사전에 정의되어 있는 데이터이다.

 

Function Call

#include <stdio.h>
void print_num(double num)
{
 	printf("%f\n", num);
}
void run_function(void function(double num), double num1)
//매개변수로 들어간 함수
{
 	function(num1);
}
int main()
{
 	run_function(print_num, 20.0);
    //함수의 포인터 전달
}

함수도 변수와 같이 함수의 매개변수로 들어갈 수 있다.

 

포인터 매개변수

#include <stdio.h>
void change_num(double* num)
{
 	*num = 10.0;
}
int main()
{
 	double num = 20.0;
 	printf("num: %f\n", num);
 	change_num(&num);
 	printf("num: %f\n", num);
}

주소값을 전달하기 때문에 입력된 변수의 값을 바꿀 수 있다. 구조체와 같이 크기가 큰 경우 속도도 빨라진다.

 

Example: 복소수 위상과 크기'

#include <stdio.h>
#include <math.h>
typedef struct
{
 	double real;
 	double imag;
} Complex;
void com_poalr(Complex num, double* phase, double* mag)
{
 	*phase = atan2(num.imag, num.real);
 	*mag = sqrt(num.real * num.real + num.imag * num.imag);
}
int main()
{
 	Complex num = {1.0, 1.0};
 	double phase, mag;
 	com_poalr(num, &phase, &mag);
 	printf("%f, %f", phase, mag);
}

반환값이 없어도 매개변수를 이용하여 출력처럼 사용할 수 있다.

 

포인터의 형변환

포인터에서 데이터 타입은 기준 크기(Unit Size)를 의미한다.

포인터의 형변환은 기준 크기의 변화이다.

#include <stdio.h>
int main()
{
 	int num = 10;
 	char* byte;
 	byte = (char*)&num;
 	for(int i = 0; i < 4; i++)
 		printf("%d\n", byte[i]);
}

반대로 4개의 char을 조합하여 우리가 원하는 int를 만들 수 있다.

 

EX)

'Control Engineering > C Programming' 카테고리의 다른 글

Preprocessor  (0) 2024.09.05
Function&Array  (0) 2024.09.04
배열(Array) 기초  (0) 2024.09.04
Practice[MAF]  (1) 2024.09.04
Practice[Integral]  (0) 2024.09.04