devWonny 2024. 12. 7. 16:25

 

 


질문

C언어와 C++ 차이가 뭔가요?

 

C++ 개발자가 두명이 있어서,C언어와 C++ 차이가 뭐냐고 물어봤다.

궁금해서 정리해보려한다.

 

C++언어와 C# 차이가 뭔가요?

 



c언어는 절차 지향 프로그래밍 언어

c++ 객체 지향 프로그래밍 언어이다.

java는 객체 지향 프로그래밍 언어이다.

 

개인적 생각:

따라서 코드를 보면 c언어는 함수 나열로만 되어있어서 import를 해오는 부분이 많다.

반면 java에서는 객체를 선언하고, 객체 안에 있는 함수를 불러다가 사용하기 떄문에 어디서 어떤 함수가 실행되는지 파악하기 쉽다.

 

c와 c++차이는 결국 oop차이로 생각하면 될 듯 하다.

 

 

더더욱 사용하기 편하게! java처럼 만든것이 C#이다.

 


 

 

 

C 예제: 학생의 성적을 계산하는 프로그램

#include <stdio.h>

// 함수 선언
void inputStudentData(char name[], int scores[], int subjectCount);
float calculateAverage(int scores[], int subjectCount);
void printResult(char name[], float average);

int main() {
    char studentName[50];
    int scores[5]; // 최대 5과목 점수
    int subjectCount = 5;

    // 1. 학생 데이터 입력
    inputStudentData(studentName, scores, subjectCount);

    // 2. 평균 계산
    float average = calculateAverage(scores, subjectCount);

    // 3. 결과 출력
    printResult(studentName, average);

    return 0;
}

// 학생 데이터 입력 함수
void inputStudentData(char name[], int scores[], int subjectCount) {
    printf("학생 이름을 입력하세요: ");
    scanf("%s", name);

    for (int i = 0; i < subjectCount; i++) {
        printf("과목 %d의 점수를 입력하세요: ", i + 1);
        scanf("%d", &scores[i]);
    }
}

// 평균 계산 함수
float calculateAverage(int scores[], int subjectCount) {
    int total = 0;
    for (int i = 0; i < subjectCount; i++) {
        total += scores[i];
    }
    return (float)total / subjectCount;
}

// 결과 출력 함수
void printResult(char name[], float average) {
    printf("\n학생 이름: %s\n", name);
    printf("평균 점수: %.2f\n", average);

    if (average >= 60) {
        printf("결과: 합격\n");
    } else {
        printf("결과: 불합격\n");
    }
}

 

C++ 예제: 학생의 성적을 계산하는 프로그램

#include <iostream>
#include <string>
#include <vector>
using namespace std;

// 학생 데이터를 표현하는 클래스
class Student {
private:
    string name;               // 학생 이름
    vector<int> scores;        // 학생 점수
    float average;             // 평균 점수

public:
    // 학생 데이터 입력
    void inputStudentData() {
        cout << "학생 이름을 입력하세요: ";
        cin >> name;

        int subjectCount;
        cout << "과목 수를 입력하세요: ";
        cin >> subjectCount;

        scores.resize(subjectCount);
        for (int i = 0; i < subjectCount; i++) {
            cout << "과목 " << i + 1 << "의 점수를 입력하세요: ";
            cin >> scores[i];
        }
    }

    // 평균 계산
    void calculateAverage() {
        int total = 0;
        for (int score : scores) {
            total += score;
        }
        average = static_cast<float>(total) / scores.size();
    }

    // 결과 출력
    void printResult() const {
        cout << "\n학생 이름: " << name << endl;
        cout << "평균 점수: " << average << endl;

        if (average >= 60) {
            cout << "결과: 합격" << endl;
        } else {
            cout << "결과: 불합격" << endl;
        }
    }
};

int main() {
    Student student; // Student 객체 생성

    // 학생 데이터 입력, 평균 계산, 결과 출력
    student.inputStudentData();
    student.calculateAverage();
    student.printResult();

    return 0;
}

 

OOP의 장점이 느껴지지 않는가?

Student의 구성요소는 name, scores, average로 되어있는것을 알수있다.

Student 는 inputStudentData(), calculateAverage(), printResult() 함수를 소지하고 있다.

 

반면 c언어는 쭈우우우우욱 읽어야 해석이 가능하다.

c언에서 이름, 점수, 평균: char studentName[50];, int scores[5]; // 최대 5과목 점수, float average

 

 

 

c#은 이벤트 프로그래밍이 가능해진다.

 

 

 

 

 

 

 


 

 

java는 클래스로 한번 캡슐화한다. 묶어서 생각하기때문에 어디 출신인지 파악이 가능하다.

반면 c언어는 계속해서 추적해야한다.

 

 

 

 

 

 

 


 

C는 클래스, 상속, 다형성이 없다. 따라서 재사용성이 낮아진다.

 

 

C#은 자바처럼 다중상속을 막고, 인터페이스로 더욱더 다형성에 힘을 싣는다.

 

 

C++ 다중 상속 예시:

class A { public: void methodA() {} };
class B { public: void methodB() {} };
class C : public A, public B {};

C obj;
obj.methodA();
obj.methodB();

 

 

C# 인터페이스 대체:

interface IA { void MethodA(); }
interface IB { void MethodB(); }

class C : IA, IB {
    public void MethodA() { Console.WriteLine("MethodA"); }
    public void MethodB() { Console.WriteLine("MethodB"); }
}

 

 

 

 

 

 

 


 

이름짓기 어렵겠는걸!

 

짖다(개)
짖다(개1)

짖다(고양이1)

짖다(고양이2)

 

// C++에서 함수 오버로딩
#include <iostream>
using namespace std;

void print(int num) {
    cout << "Number: " << num << endl;
}

void print(double num) {
    cout << "Double: " << num << endl;
}

int main() {
    print(10);    // 정수 출력
    print(3.14);  // 실수 출력
    return 0;
}

 

 

 

 

 

 

 

 


 

 

C, C++ 자바에 비해 개발자가 메모리까지 관리해야한다니! 정말 아는게 많아야 한다!

예시: 동적 메모리 할당

// C 코드
int* arr = (int*)malloc(10 * sizeof(int)); // 타입 캐스팅 필요
free(arr);

// C++ 코드
int* arr = new int[10]; // 타입 캐스팅 필요 없음
delete[] arr;

 

 

 

그래서 나온게 C# 자바처럼 가비지 콜렉터가 메모리를 자동으로 해제해준다

 

 

 

 




 

예시: C++ STL 사용

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> numbers = {1, 2, 3};
    numbers.push_back(4); // 동적으로 데이터 추가
    for (int n : numbers) {
        cout << n << " ";
    }
    return 0;
}

 

 

 

 

C++ STL 벡터:

 
#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> numbers = {1, 2, 3};
    numbers.push_back(4);
    for (int n : numbers) {
        cout << n << " ";
    }
    return 0;
}

 

C# 리스트:

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        List<int> numbers = new List<int> { 1, 2, 3 };
        numbers.Add(4);
        foreach (int n in numbers) {
            Console.Write(n + " ");
        }
    }
}

 

C#에는 collection이 있다고?! 이건 java아닌가?!

collection 라이브러리로 인해 다형성이 강화되었다! 다양한 타입을 같은 함수로 순회가 가능해진다!

 

 

 

 

 

 


 

C언어 예외처리도 없었던거냐???

C++ 예외 처리:

#include <iostream>
using namespace std;

int main() {
    try {
        throw "An error occurred"; // 예외 발생
    } catch (const char* e) {
        cout << e << endl; // 예외 처리
    }
    return 0;
}

 

C# 예외 처리:

using System;

class Program {
    static void Main() {
        try {
            throw new Exception("An error occurred");
        } catch (Exception ex) {
            Console.WriteLine(ex.Message);
        } finally {
            Console.WriteLine("Cleanup code runs here.");
        }
    }
}

 

 

 

C 예외 처리:

 

// 1. 조건문을 활용한 간단한 예외 처리
// C에서는 함수에서 에러 발생 시 반환 값을 이용해 예외 처리를 흉내 낼 수 있습니다.
// 예시: 숫자를 0으로 나누는 경우 처리
#include <stdio.h>

// 함수 선언
int divide(int numerator, int denominator);

int main() {
    int a = 10, b = 0;
    int result = divide(a, b);

    if (result == -1) {
        printf("에러: 0으로 나눌 수 없습니다.\n");
    } else {
        printf("결과: %d\n", result);
    }
    return 0;
}

// 나눗셈 함수
int divide(int numerator, int denominator) {
    if (denominator == 0) {
        return -1; // 오류 코드 반환
    }
    return numerator / denominator;
}


// 2. 함수 포인터와 콜백을 이용한 예외 처리
// C에서는 함수 포인터를 이용해 오류 발생 시 특정 동작을 수행하도록 설정할 수 있습니다.
// 예시: 콜백 함수로 예외 처리
#include <stdio.h>

void onError(const char* errorMessage) {
    printf("에러 발생: %s\n", errorMessage);
}

int divide(int numerator, int denominator, void (*errorCallback)(const char*)) {
    if (denominator == 0) {
        errorCallback("0으로 나눌 수 없습니다.");
        return -1; // 오류 코드 반환
    }
    return numerator / denominator;
}

int main() {
    int a = 10, b = 0;
    int result = divide(a, b, onError);

    if (result != -1) {
        printf("결과: %d\n", result);
    }

    return 0;
}



//3. setjmp와 longjmp를 이용한 예외 처리
// C 표준 라이브러리의 <setjmp.h>를 사용하면 예외 처리를 흉내 낼 수 있습니다.
// setjmp는 현재의 실행 상태를 저장하고, longjmp는 저장된 상태로 다시 돌아가 실행을 계속합니다.
//예시: 0으로 나누는 경우 예외 처리

#include <stdio.h>
#include <setjmp.h>

jmp_buf jumpBuffer; // 예외 발생 시 되돌아갈 위치 저장

void divide(int numerator, int denominator) {
    if (denominator == 0) {
        printf("에러: 0으로 나눌 수 없습니다.\n");
        longjmp(jumpBuffer, 1); // 예외 발생 시 setjmp로 되돌아감
    }
    printf("결과: %d\n", numerator / denominator);
}

int main() {
    if (setjmp(jumpBuffer) == 0) {
        // 정상 실행
        divide(10, 2);  // 정상 실행
        divide(10, 0);  // 예외 발생
    } else {
        // longjmp로 복귀했을 때 실행
        printf("예외 처리 완료.\n");
    }
    return 0;
}


//4. 사용자 정의 매크로를 이용한 예외 처리
//매크로와 goto를 조합하여 간단한 예외 처리를 구현할 수 있습니다.
//예시: 매크로로 예외 처리
#include <stdio.h>

#define THROW_ERROR(msg) do { printf("에러: %s\n", msg); goto error; } while (0)

int main() {
    int a = 10, b = 0;

    if (b == 0) {
        THROW_ERROR("0으로 나눌 수 없습니다.");
    }

    printf("결과: %d\n", a / b);
    return 0;

error:
    printf("예외 처리 완료.\n");
    return -1;
}

 

 

 

 

 


 

아 그래서 게임에서 c++을 사용하는 이유가, 메모리를 커스텀하기 위함과 동시에 자바처럼 oop를 사용하기 위해 c++를 사용하기 위함이군!

 

 

둘다 게임에 적합!

성능이 중요해? C++

개발자가 편하게? C#

 

 

 

C#은 성능은 낮췄지만, 편의성에 초점을 맞춘다