C/C++와 JAVA 비교
C/C++와 Java를 비교해보면 아래와 같다.
구분 | C | C++ | JAVA |
---|---|---|---|
#typedef |
O | O | X |
#define |
O | O | X |
#goto |
O | O | X |
struct(구조체) 자료형 | O | O | X |
Union 자료형 | O | O | X |
데이터형 변환 | 묵시적 | 명시적 | 랩퍼 클래스 |
배열 | 포인터 | 포인터 | 객체 |
문자열 | 배열 | 배열 | String 자료형 |
메모리 관리 | 수동 | 수동 | 자동 |
객체지향 개념 | 비 객체지향 (절차 지향) | 반 객체지향 | 객체지향 |
연산자 오버로딩 | X | O | X |
함수(메소드) 오버로딩 | X | O | O |
다중 상속 | X | O | X |
운영체제 독립성 | X | X | 비종속 |
main function
모든 프로그램들은 최초 실행 때에 시작 진입점을 가지게 되는데 C++에서는 main 함수가 되며 Java에서도 동일한 이름의 main 메소드가 프로그램의 진입점이 된다.
예제 1-1)과 예제 1-2)를 비교해보면 약간의 모양은 다른 부분이 있지만 거의 비슷해 보인다.
예제 1-1) C++ main function
#include <iostream>
int main(int argc, const char * argv[])
{
std::cout << "Hello, World!\n";
return 0;
}
예제 1-2) 자바 main method
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
C/C++의 main과 Java의 main을 비교해보면 아래와 같다.
구분 | C/C++ | Java |
---|---|---|
return | int | void |
parameter | int argc, const char * argv[] | String[] args |
위치 | 클래스 밖에 있다. | 클래스 안에 있다. |
C/C++은 return은 보통은 정수인데 컴파일러에 따라 void도 존재한다. parameter도 맞찮가지로 컴파일러에 따라 없을 수도 있다.
프로그램 안에 main은 자바에 달리 클래스 밖에 존재하는데 이는 모든 것을 객체화한다는 객체 지향 언어 프로그래밍(object-oriented programming)에 위배된다고 하여 완벽한 객체 지향 언어가 아닌 반 객체 지향이라고도 한다.
define 메크로
C/C++와 비교해 Java에 없는 것중에 하나는 전처리문이다. 그 중 #define
문에 대해서 설명한다.
#define
와 같은 문은 일명 메크로라고도 하는데 값, 함수를 지정한 것을 대체 치환해 주어 프로그래밍을 편하게 해준다. 여기서 치환해 준다는 것은 Java와 달리 C++ 컴파일에서는 전처리라는 소스 치환 과정을 있는데 실제 소스에 define된 값을 실제 값, 함수로 변환해주는 과정이다.
*예제2-1)*와 *예제2-2)*를 전처리 전후를 비교하면서 보자.
예제2-1) C++ 소스 코드
#include <iostream>
#define HELLO "Hello, World!\n"
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
int main(int argc, const char * argv[])
{
std::cout << HELLO;
std::cout << "Max:" << MAX(10, 100);
return 0;
}
예제2-2) C++ 전처리 후의 소스 코드
# 1 "main.cpp"
# 1 "<built-in>"
... 중간생략 ...
# 10 "main.cpp" 2
int main(int argc, const char * argv[])
{
std::cout << "Hello, World!\n";
std::cout << "Max:" << ( (10) > (100) ? (10) : (100) );
return 0;
}
전처리 파일을 컴파일마다 다르게 보일 수 있다. 예제는 g++로 만든 전처리 파일이다.
위에 소스를 보면 메크로 값 HELLO와 메크로 함수 MAX(a, b)
에 주목하자. 개발자가 작성한 소스 파일이 전처리 과정을 거치고 HELLO는 실제 값인 “Hello, World!\n"이 들어가고 MAX(a, b)
은 ( (10) > (100) ? (10) : (100) )
으로 변경된 것을 볼수 있다.
그럼 Java에서는 define인 아예 없는 것인가? 대답은 “그렇다"이다. 하지만 값 치환은 비슷하게 코드를 만들 수는 있다. *예제2-3)*을 보자.
예제2-3) Java 소스 코드
public class Main {
public static final String HELLO = "Hello, World!\n";
public static void main(String[] args) {
System.out.println(HELLO);
}
}
예제2-3) Java 소스 코드는 HELLO 변수에 static, final로 지정하고 값을 대입하여 이를 출력하도록 했다. 이 소스를 컴파일하면 바이트 코드가 나오고 이를 다시 역컴파일 하면 C++의 define문과 비슷하게 치환되어 나오는걸 볼수 있다.
예제2-3) Java 역컴파일
public class Main
{
public Main()
{
}
public static void main(String args[])
{
System.out.println("Hello, World!\n");
}
public static final String HELLO = "Hello, World!\n";
}
실제로 *예제2-3)*가 역컴파일을 한 것이다. println에 넣었던 HELLO는 사라지고 실제 값인 "Hello, World!\n"
으로 치환되어 있는 것을 확인할 수 있다.
이렇게 C++나 Java에서 치환되는 것이 실제 프로그램이 구동할 때 메모리에 관리되는 변수보다는 실제값이 직접 들어가게 되므로 아주 조금은 속도가 향상될 것으로 생각된다. 하지만 이 속도가 너무나 미세하기에 단순히 프로그램의 속도 향상을 위한 목적이라면 define을 쓰지는 말길 바란다. 오히려 너무 난발하면 디버깅이 힘든 프로그램이 되기에 주의를 요한다.