C, C++

[C] Cμ–Έμ–΄ 기초

벼리01 2024. 8. 9. 16:35

πŸ“Œμ „μ—­λ³€μˆ˜/μ§€μ—­λ³€μˆ˜

Cμ–Έμ–΄μ˜ μ „μ—­λ³€μˆ˜λŠ” mainν•¨μˆ˜ λ°”κΉ₯에 μ„ μ–Έν•œλ‹€. ⇒ μ§€μ–‘ν•  것.

정적 λ³€μˆ˜λŠ” static ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œλ‹€. ν•¨μˆ˜κ°€ λλ‚˜λ„ μ†Œλ©Έλ˜μ§€ μ•ŠλŠ”λ‹€.

 

 

πŸ“Œν¬μΈν„°

* ν‚€μ›Œλ“œλ₯Ό λΆ™μ—¬μ„œ μ„ μ–Έν•œλ‹€. (κ°„μ ‘ μ—°μ‚°μžμ™€ λ‹€λ₯Έ 의미λ₯Ό κ°€μ§€λ―€λ‘œ ν—·κ°ˆλ¦¬μ§€ 말 것. ν¬μΈν„°μž„μ„ λͺ…μ‹œν•˜λŠ” ν‚€μ›Œλ“œλ‘œ μƒκ°ν•˜μž.)

 

int a = 1;
int *ptr = &a;

 

포인터 λ³€μˆ˜λŠ” λ©”λͺ¨λ¦¬μ˜ μ£Όμ†Œλ₯Ό κ°€μ§„λ‹€. μ£Όμ†Œ 값은 μ •μˆ˜λ‘œ λ˜μ–΄μžˆμœΌλ―€λ‘œ 4byteκ°€ λœλ‹€. (단, 64λΉ„νŠΈμ˜ 경우 8byteκ°€ 될 수 μžˆλ‹€.)

& μ£Όμ†Œ μ—°μ‚°μž: μ£Όμ†Œλ₯Ό λ°˜ν™˜ν•œλ‹€.

* κ°„μ ‘ μ—°μ‚°μž: κ·Έ μ£Όμ†Œμ— κ°€μ„œ 값을 λ°˜ν™˜ν•œλ‹€.

 

 

이쀑 포인터(ν¬μΈν„°μ˜ 포인터)

int a = 1;

int* ptr = &a;
int** ptrPtr = &ptr;

 

void 포인터

νƒ€μž…μ„ μ•Œ 수 μ—†μ§€λ§Œ μ£Όμ†Œλ₯Ό μ €μž₯ν•˜κ³  싢을 λ•Œ μ‚¬μš©ν•œλ‹€.

int a = 1;

void* ptr = &a;

printf("%d\\n", *voidPtr); // λͺ‡ byteλ₯Ό 읽을 μ§€ μ•Œ 수 μ—†λ‹€. Error!
printf("%d\\n", *(int*)voidPtr); // 포인터λ₯Ό μ •μˆ˜ν˜• ν¬μΈν„°λ‘œ ν˜•λ³€ν™˜ν•œλ‹€.

 

 

πŸ“Œλ°°μ—΄

λ°°μ—΄μ˜ 이름에 λ§μ…ˆ λ˜λŠ” λΊ„μ…ˆ 연산을 ν•  경우 ν•΄λ‹Ή κ°’μ˜ μžλ£Œν˜• 크기만큼 μ΄λ™ν•œ μ£Όμ†Œ 값을 λ°˜ν™˜ν•œλ‹€.

Cμ–Έμ–΄μ˜ 배열은 μƒμˆ˜λ‘œ μ„ μ–Έν•΄μ•Ό ν•œλ‹€.

int size = 5;
int arr[size]; // μ—λŸ¬!

 

 

λ°°μ—΄μ˜ 길이가 λͺ…μ‹œλ˜μ§€ μ•Šμ€ 경우 초기 κ°’μ˜ κ°œμˆ˜λŒ€λ‘œ μ΄ˆκΈ°ν™”ν•œλ‹€.

int arr[] = {1, 2, 3, 4, 5};

 

 

포인터와 λ°°μ—΄

λ°°μ—΄μ˜ 이름은 ν•΄λ‹Ή λ°°μ—΄ 첫 번째 μš”μ†Œμ˜ μ£Όμ†Œ 값을 κ°€μ§„λ‹€. ⇒ λ°°μ—΄ λ³€μˆ˜λŠ” λ°°μ—΄ 첫 번째 μš”μ†Œμ˜ μ£Όμ†Œλ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터가 λœλ‹€.

단, λ°°μ—΄μ˜ 이름은 포인터 μƒμˆ˜κ°€ λ˜λ―€λ‘œ λ³€κ²½ν•  수 μ—†λ‹€.

λ°°μ—΄μ˜ 이름에 λ§μ…ˆ 연산을 ν•  경우 ν•΄λ‹Ή μžλ£Œν˜•μ˜ 크기만큼 μ΄λ™ν•œ μ£Όμ†Œ 값을 λ°˜ν™˜ν•œλ‹€. μ •μˆ˜ν˜• λ°°μ—΄μ˜ 경우 1을 λ”ν•˜λ©΄ 4byte만큼 μ΄λ™ν•œ μ£Όμ†Œ 값이 λœλ‹€.

int arr[] = {1, 3, 5, 7, 9};

arr + 1 // λ‘λ²ˆμ§Έ μš”μ†Œμ˜ μ£Όμ†Œκ°’
*(arr + 1) // λ‘λ²ˆμ§Έ μš”μ†Œ
*arr + 1 // κ°„μ ‘ μ—°μ‚°μž(*)κ°€ λ¨Όμ € 연산을 λ§ˆμΉ˜λ―€λ‘œ, λ°°μ—΄μ˜ 첫번째 μš”μ†Œμ— 1을 λ”ν•œ 값이 λœλ‹€.

 

 

λ°°μ—΄μ˜ 이름이 포인터기 λ•Œλ¬Έμ—, 포인터λ₯Ό λ°°μ—΄μ˜ μ΄λ¦„μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€.

κ°„μ ‘ μ—°μ‚°μž λ˜λŠ” λ°°μ—΄μ²˜λŸΌ 인덱슀λ₯Ό λΆ™μ—¬ 값을 ν˜ΈμΆœν•  수 μžˆλ‹€.

 

int arr[] = { 1, 3, 5, 7, 9 };
printf("%d\\n", *(arr + 1)); // 3

int* pTemp = arr;
printf("%d\\n", *(pTemp + 1)); // 3
printf("%d", pTemp[1]); // 3

 

 

 

포인터 λ°°μ—΄

포인터 λ³€μˆ˜ μ—¬λŸ¬ 개λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•œ λͺ©μ μœΌλ‘œ μ„ μ–Έλ˜λŠ” λ°°μ—΄. μš”μ†Œλ‘œ 포인터 λ³€μˆ˜λ₯Ό κ°€μ§„λ‹€.

const char *pArr[] = {"Cμ–Έμ–΄", "μžλ°”", "베이직"};

 

 

2차원 λ°°μ—΄

ν–‰(row)κ³Ό μ—΄(column)을 κ°€μ§„ λ°°μ—΄. λ°°μ—΄μ˜ λ°°μ—΄. λ‹€μŒκ³Ό 같이 μ„ μ–Έν•œλ‹€.

int arr[i][j]; // iλŠ” ν–‰, jλŠ” μ—΄

 

 

<4ν–‰ 3열을 κ°€μ§„ 2차원 λ°°μ—΄>

2차원 λ°°μ—΄ 이름에 1차원 λ°°μ—΄μ²˜λŸΌ 초기 값을 넣더라도, κ²°κ³ΌλŠ” 2차원 λ°°μ—΄λ‘œ λ‚˜μ˜¨λ‹€.

 

int arr[2][3] = {1, 2, 3, 4, 5, 6};

== { {1, 2, 3}, {4, 5, 6} }

 

πŸ“Œλ¬Έμžμ—΄

문자λ₯Ό κ°€μ§„ λ°°μ—΄. λ°°μ—΄μ˜ 끝에 \\0 nullλ¬Έμžκ°€ ν¬ν•¨λœλ‹€. μ–΄λ””μ„œλΆ€ν„° μ–΄λ””κΉŒμ§€ 읽을지 μ•Œ 수 μ—†μœΌλ―€λ‘œ, \\0(NULL) 문자λ₯Ό λ§Œλ‚˜λ©΄ λ¬Έμžμ—΄μ˜ 끝으둜 κ°„μ£Όν•œλ‹€.


`char str[100] = "Hello, World!"` κ³Ό 같이 μ΄ˆκΈ°ν™” ν–ˆμ„ λ•Œ, 100개의 λ¬Έμžκ°€ λ“€μ–΄κ°ˆ 수 μžˆλŠ” 곡간을 ν• λ‹Ήλ°›λŠ”λ‹€. μ΄λ•Œ `Hello, World!` 만 μ΄ˆκΈ°ν™” λ˜μ—ˆμœΌλ―€λ‘œ λ‚˜λ¨Έμ§€ 뒀에 μžˆλŠ” 값은 μ“°λ ˆκΈ°κ°’μ„ κ°€μ§€κ²Œ λœλ‹€. μ΄λ•Œ 컴퓨터가 λ¬Έμžμ—΄μ˜ 끝을 ꡬ뢄할 수 μžˆλ„λ‘ `\0`(null) 문자λ₯Ό μ‚½μž…ν•œλ‹€. 즉 null 문자λ₯Ό λ§Œλ‚˜λŠ” μˆœκ°„ λ¬Έμžμ—΄μ˜ 끝으둜 νŒλ‹¨ν•œλ‹€.(λ’€μ˜ λͺ¨λ“  값은 λ¬΄μ‹œν•œλ‹€.)

 

char charArr[] = "Hello World!";
printf("%s\\n", charArr); // Hello World!

charArr[5] = '\\0';
printf("%s\\n", charArr); // Hello
char str[100] = "Beautiful"; 
printf("%s", str);	//	Beautiful

char str2[100] = "Hello\0 World";
printf("%s", str2);	//	Hello

 

 

πŸ“Œν•¨μˆ˜

ν•¨μˆ˜μ™€ 포인터

기본적인 ν•¨μˆ˜μ˜ 인자 전달 ν˜•νƒœλŠ” 볡사. (call by value: 값에 μ˜ν•œ 호좜) μ‹€μΈμˆ˜(μ „λ‹¬ν•˜λŠ” 주체) → ν˜•μ‹μΈμˆ˜

int main(){

	int a = 10;
	func(a); // aλŠ” μ‹€μΈμˆ˜
	return 0;
}

void func(int b){ // bλŠ” ν˜•μ‹μΈμˆ˜
	...
}

 

 

 

배열을 μ „λ‹¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” ν¬μΈν„°λ‘œ λ°›λŠ”λ‹€.

ν•¨μˆ˜μ— μ „λ‹¬ν•˜κ³ μž ν•˜λŠ” 값이 μ—¬λŸ¬ 개일 λ•Œ, 배열을 전달 인자둜 μ‚¬μš©ν•  수 μžˆλ‹€. (λ°°μ—΄μ˜ 이름은 포인터. )

μ΄λ•Œ 전달 λ°›λŠ” μΈμžκ°€ 포인터 λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, 원본 λ°°μ—΄μ˜ 크기λ₯Ό μ•Œ 수 μ—†λ‹€. sizeof λ₯Ό μ‚¬μš©ν•  경우 ν¬μΈν„°μ˜ μ‚¬μ΄μ¦ˆμΈ 4 κ°€ 좜λ ₯ λœλ‹€.

Cμ–Έμ–΄μ—μ„œλŠ” length λ₯Ό μƒμˆ˜λ‘œ κ°€μ§€λŠ” 타 언어와 달리 원본 λ°°μ—΄μ˜ 크기λ₯Ό λ”°λ‘œ 전달해야 ν•œλ‹€.

#include <stdio.h>

int func(int *pArr, int size) {

	int sum = 0;

	for (int i = 0; i < size; i++) {
		sum += pArr[i];
	}

	return sum;
}

int main() {

	int arr[] = { 1, 2, 3, 4, 5 };
	int result = func(arr, sizeof(arr) / sizeof(arr[0]));

	printf("%d\\n", result);

	return 0;
}

 

 

 

 

ν•¨μˆ˜ 포인터

ν•¨μˆ˜μ˜ μ£Όμ†Œκ°’μ„ μ €μž₯ν•œλ‹€.

// μžλ£Œν˜•(*ν•¨μˆ˜ 포인터 이름)(인자 λͺ©λ‘)
int (*func)(int a);

 

#include <stdio.h>

int Plus(int a, int b) {
	return a + b;
}

int Minus(int a, int b) {
	return a - b;
}

int main() {

	int (*funcPtr)(int a, int b);

	funcPtr = Plus;
	funcPtr = Minus;

	printf("%d", funcPtr(12, 2));

	return 0;
}

 

 

ν•¨μˆ˜μ˜ 동적 바인딩을 μœ„ν•΄ μ‚¬μš©ν•  수 μžˆλ‹€. 컴파일 μ‹œμ μ— κ³ μ •λœ 할당이 μ•„λ‹ˆλΌ λŸ°νƒ€μž„μ—μ„œλ„ ν•¨μˆ˜κ°€ 변경될 수 μžˆλ„λ‘ ν•œλ‹€. ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑에 μ–΄λ–€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν• μ§€ κ²°μ •ν•  수 μžˆλ‹€.(동적 ν•¨μˆ˜ 호좜)

 

void func(int a, int b, void (*callback)()) {
	...
}

 

ν•¨μˆ˜ ν¬μΈν„°λŠ” μ°Έμ‘°ν•˜κ³ μž ν•˜λŠ” ν•¨μˆ˜μ˜ 선언뢀와 μ™„μ „νžˆ μΌμΉ˜ν•΄μ•Ό ν•œλ‹€. (λ°˜ν™˜ μžλ£Œν˜•κ³Ό λ§€κ°œλ³€μˆ˜ νƒ€μž… λ˜λŠ” μˆœμ„œκ°€ λͺ¨λ‘ μΌμΉ˜ν•΄μ•Όν•¨)

ν•¨μˆ˜ 포인터가 μ°Έμ‘°ν•˜κ³  μžˆλŠ” μ£Όμ†Œκ°€ μœ νš¨ν•œμ§€ ν™•μΈν•΄μ•Όν•œλ‹€. 잘λͺ»λœ μ£Όμ†Œλ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜ `null` 을 μ°Έμ‘°ν•  경우 ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ  수 μžˆλ‹€.

 

 

 

 

 

πŸ“ŒCall by Value / Call by Reference

값에 μ˜ν•œ 호좜(Call by value)

μ‹€ 인수의 값을 ν˜•μ‹ μΈμˆ˜κ°€ λ³΅μ‚¬ν•΄μ„œ λ„˜κ²¨ λ°›λŠ”λ‹€. μ‹€ μΈμˆ˜κ°€ μ €μž₯된 μ£Όμ†Œ κ°’κ³Ό ν˜•μ‹ μΈμˆ˜κ°€ μ €μž₯된 μ£Όμ†Œ 값이 μΌμΉ˜ν•˜μ§€ μ•ŠλŠ”λ‹€.

참쑰에 μ˜ν•œ 호좜(Call by reference)

μ‹€ μΈμˆ˜κ°€ μ°Έμ‘°ν•˜κ³  μžˆλŠ” μ£Όμ†Œμ˜ 값을 ν˜•μ‹ μΈμˆ˜κ°€ μ°Έμ‘°ν•œλ‹€.

ν•¨μˆ˜ λ‚΄μ—μ„œ 데이터λ₯Ό λ³€κ²½ν•˜λ©΄ 원본 데이터도 λ³€κ²½λœλ‹€. (얕은 볡사)

 

 

 

πŸ“ŒμŠ€νƒ/νž™ λ©”λͺ¨λ¦¬

μŠ€νƒλ©”λͺ¨λ¦¬

LIFO(Last In First Out: ν›„μž…μ„ μΆœ). ν•¨μˆ˜λ₯Ό μœ„ν•œ 곡간. μ œν•œλœ 크기와 λΉ λ₯Έ 속도. 각 ν•¨μˆ˜λŠ” μžμ‹ μ˜ μŠ€νƒ ν”„λ ˆμž„μ„ κ°€μ§€λ©°, 여기에 μ§€μ—­ λ³€μˆ˜, 맀개 λ³€μˆ˜, 리턴 될 μ£Όμ†Œ(ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ μœ„μΉ˜)κ°€ ν¬ν•¨λœλ‹€.

 

νž™ λ©”λͺ¨λ¦¬

동적 λ©”λͺ¨λ¦¬. κ°œλ°œμžκ°€ 직접 ν• λ‹Ήν•œλ‹€. (malloc calloc free) μˆ˜λ™μœΌλ‘œ 관리해야 함. μŠ€νƒλ³΄λ‹€ 크닀. free() 둜 λ©”λͺ¨λ¦¬κ°€ ν•΄μ œλ˜κΈ° μ „κΉŒμ§€ μœ μ§€λœλ‹€. ⇒ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ 주의!

큰 λ°°μ—΄μ΄λ‚˜ 객체λ₯Ό λ™μ μœΌλ‘œ ν• λ‹Ήν•  λ•Œ.

(μžλ°”μ˜ 경우 new ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ νž™ λ©”λͺ¨λ¦¬μ— μ˜¬λΌκ°„λ‹€. 더이상 μ°Έμ‘°λ˜μ§€ μ•ŠλŠ” 객체의 λ©”λͺ¨λ¦¬λŠ” κ°€λΉ„μ§€ 컬렉터에 μ˜ν•΄ μžλ™μœΌλ‘œ ν•΄μ œλœλ‹€. static λ³€μˆ˜λŠ” νž™μ΄ μ•„λ‹ˆλΌ λ©”μ„œλ“œ μ˜μ—­μ— μ €μž₯λœλ‹€.)

 

'C, C++' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[C++] 상속(Inheritance)  (0) 2024.08.29
[C++] 객체 μ§€ν–₯  (6) 2024.08.19
[C] 동적 λ©”λͺ¨λ¦¬ ν• λ‹Ή  (0) 2024.08.13
[C] ꡬ쑰체, 곡용체  (0) 2024.08.13
[C++] 기초  (0) 2023.08.25