본문 바로가기
Programming Language/C++

[C++] C++의 기본 (2)

by spareone 2025. 4. 30.

1. Inline Function

C언어에서는 동작을 정의할 수 있는 방법으로 매크로와 함수가 존재합니다.

#define ADD(x,y) ((x)+(y)) // x와 y를 더함
 
int main() {
ADD(3, 5);
}

위 코드는 매크로로 ADD 연산을 정의했습니다.
매크로는 전처리 단계에서 해당 내용을 통째로 치환한 뒤 컴파일이 진행됩니다.
이로 인해 매크로 내용이 길면 파일 크기가 커질 수 있습니다.

ex) 위 코드에서 ADD(3, 5)는 ((3) + (5))로 치환되어 컴파일

반면 함수의 경우 다음과 같이 사용합니다.

int add(int x, int y) {
return x + y;
}
 
int main() {
add(3, 5);
}

add() 함수를 정의한 모습입니다. 매크로와 달리, 함수의 경우 해당 함수의 주소로 이동하여 연산을 진행하게 됩니다.
이로 인해 매크로보다는 시간이 조금 더 걸립니다.

하지만 매크로는 개발자가 의도하지 않은 연산이 수행될 수도 있습니다.
CERT C에서는 이를 취약점으로 간주하며, 위험성이 있다고 판단하여 매크로보다 인라인 함수를 사용하도록 권장하고 있습니다.

참고 : http://spareone.io/275

inline int add(int x, int y) {
return x + y;
}
 
int main() {
add(3, 5);
}

인라인 함수는 앞에 inline을 붙여주면 되며, 매크로처럼 함수의 내용을 치환하지만 매크로보다 안전하게 수행됩니다.
다만 무조건 인라인 함수로 실행이 되지는 않으며, 컴파일러에 따라 인라인으로 될 수도 있고 안 될 수도 있습니다.

2. Reference

C++에는 참조(reference)의 개념이 도입되었습니다.
변수에 대한 또 다른 이름이라고 보면 됩니다.

int a = 5;
int &ref = a; // 선언과 동시에 초기화
 
ref = 4 // a도 4가 됨

reference를 선언할 때는 앞에 &를 붙여주며, 위 코드처럼 선언과 동시에 초기화되어야 합니다.
이렇게 되면 이제 a와 ref는 완전히 같은 변수가 됩니다. (같은 공간을 가리키며, ref의 값을 4로 변경하면 a도 4가 됩니다.)

int a = 5;
int b = 6;
 
int *p = &a; // p는 a를 가리키도록 선언
p = &b; // 이제 p는 b를 가리킴 (b의 주소값을 가짐)
 
int &ref = a; // a와 동일한 변수
ref = b; // b 값을 ref에 대입. 즉, a에 b 값이 들어감. (주의 : ref가 b와 동일한 변수가 되는 것이 아님)

위 코드는 reference와 포인터의 다른 점을 설명한 코드입니다.
포인터는 해당 변수에 저장된 주소를 변경할 수 있습니다. 따라서 a를 가리킨 뒤 b를 가리키도록 변경할 수 있습니다.

하지만 reference는 그렇지 않습니다. 선언 후 초기화를 하면 변경이 불가능합니다.
따라서 위의 코드 마지막 라인은 주석의 설명처럼 동작하게 됩니다.

int a = 5;
int b = 3;
int &ref = a + b; // error
int &ref = 5; // error

reference는 변수를 참조하기 때문에 이렇게 직접적으로 값을 대입할 수 없습니다.

3. Function References

함수에 대해서도 reference를 정의할 수 있습니다.

int add(int x, int y) {
return x + y;
}
 
int main() {
int (&pAdd)(int, int) = add; // Function Reference
pAdd(4,5);
}

pAdd와 add는 같은 함수가 됩니다.

4. Call by Reference

C언어에서는 함수 호출 방식이 2가지였습니다. (참고 : http://spareone.io/676)

  • Call by Value – 값에 의한 전달
  • Call by Address – 주소값에 의한 전달

C++에서는 Call by Reference(참조에 의한 전달)가 추가되었습니다.

void swap(int &x, int &y) {
int temp = y;
x = y;
y = temp;
}
 
int main() {
int a = 3, b = 5;
swap(a, b);
}

swap(a, b)를 실행하게 되면, a는 &x로 전달받고 b는 &y로 전달받게 되어 각각의 두 변수는 완전히 동일한 변수가 됩니다.
Call by Reference를 이용하면 위 코드처럼 포인터를 사용하지 않고 swap()을 구현할 수 있습니다.

5. Return by Reference

reference를 return하는 것도 가능합니다.

int z;
 
int &sum(int x, int y) {
z = x + y;
return z;
}
 
int main() {
sum(3, 5);
}

위 코드는 z의 공간을 반환합니다.

int *min(int &x, int &y) {
return ((x < y) ? x : y);
}
 
int main() {
int a = 3, b = 5;
min(a, b) = 6;
 
cout << a << ' ' << b << '\n';
}

Call by Reference를 때리고 Return by Reference를 하는 것도 가능하기 때문에, 위와 같은 코드가 나올 수 있습니다.
a, b를 Call by Reference로 보내게 되면, a 공간의 값과 b 공간의 값 중 작은 공간을 반환합니다.
min(a, b) = 6의 의미는 min()에서 반환된 공간에 6을 대입하겠다는 것이며, 위의 예제에서는 a에 6이 들어갈 것입니다.

6. linkage 지정

C언어와 C++는 함수를 다른 방식으로 저장합니다.

  • C언어 : 함수 이름으로 저장
  • C++ : 함수 이름과 매개 변수의 개수와 타입을 저장 (mangled name)

C에서 정의한 함수를 C++에서 사용하고 싶을 때, 저장 방식이 달라 함수를 불러오지 못하는 상황이 발생할 수 있습니다.
이런 문제점이 발생할 경우, C++ 컴파일러에서 강제로 C언어 방식으로 함수를 저장(함수 이름만 저장)하도록 코드를 작성할 수 있습니다.

extern "C" int func(int a);
 
extern "C" {
int func(int a);
int func2(int b);
}
 
extern "C" {
#include "lib.h" // 헤더 파일도 지정 가능
}

<stdio.h>에는 이미 linkage 지정이 되어 있기 때문에 scanf() 등의 함수를 C++에서 사용할 수 있는 것입니다.

7. declaration and definition

선언과 정의에 관련된 내용입니다. 이 두 개는 혼동해서 사용하기 쉬운데, 다른 의미를 가지고 있습니다.

// 선언만 한 경우
int func(int);
struct Point;
 
// 선언과 정의를 한 경우
int a;
int func(int x) {return x}
struct Point { int x; int y; };

정의를 하면 동시에 선언도 하게 되지만, 선언을 한다고 해서 모두 정의가 되지는 않습니다.

다음은 선언이지만 정의는 아닌 것들입니다.

  1. function prototype
  2. extern variable (단, 초기화 구문 포함 시 정의가 됨)
  3. extern function (단, 함수 본문 포함 시 정의가 됨)
  4. class 또는 struct 내에 선언된 static 멤버 변수
  5. class name 또는 struct name 선언
  6. typedef 선언
  7. using 선언

동일한 식별자의 선언은 2번 이상 나올 수 있으나, 중복해서 정의가 될 수는 없습니다.

같은 헤더 파일을 여러 번 include할 수 없습니다.


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

[C++] 클래스와 객체  (0) 2025.04.30
[C++] C++의 기본 (1)  (0) 2025.04.30
[C++] C언어 살펴보기  (0) 2025.04.30

댓글