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을 쓰지는 말길 바란다. 오히려 너무 난발하면 디버깅이 힘든 프로그램이 되기에 주의를 요한다.