Skip to Content
독학사독학사 4단계통합프로그래밍01. C·Java 기초 문법 빠른 복습과 독학사 스타일 문항 맛보기

이번 문서의 목표: 이 파일을 다 읽으면 C와 Java의 기본 문법(자료형·연산자·제어문·함수/메서드)을 나란히 놓고 차이를 설명할 수 있고, 코드를 한 줄씩 실행 추적하며 결과를 예측하는 습관을 갖출 수 있으며, 독학사 통합프로그래밍의 세 가지 대표 문항 유형(빈칸 채우기·실행 결과 예측·오류 찾기)을 실제로 풀어 낼 수 있다.

왜 문법을 다시 복습해야 하는가

여러분은 이미 2단계 C프로그래밍, 3단계 객체지향프로그래밍(Java)을 거쳤거나 그에 준하는 지식을 갖췄다고 전제합니다. 그런데도 이 편에서 문법을 다시 훑는 이유는, 통합프로그래밍 시험이 C와 Java를 같은 문제지 안에서 번갈아 묻기 때문입니다. 한 문제는 C의 printf(프린트에프, 형식화된 출력을 하는 표준 함수) 결과를 묻고, 바로 다음 문제는 Java의 System.out.println(시스템 아웃 프린트라인, 콘솔에 한 줄을 출력하는 메서드) 결과를 묻는 식입니다. 두 언어를 따로따로는 알아도, 같은 순간에 머릿속에서 전환하는 훈련이 안 되어 있으면 사소한 문법 차이(세미콜론 위치, 배열 선언 방식, %d%s 같은 서식 지정자)에서 실점하기 쉽습니다.

쉽게 말하면: 이 편은 두 언어를 처음부터 다시 가르치는 자리가 아니라, 이미 아는 두 언어를 “같은 문제지 안에서 헷갈리지 않고 전환”하도록 나란히 놓고 대조하는 자리입니다.

1. 자료형과 연산자 비교

C와 Java는 둘 다 정적 타입 언어(변수의 자료형을 컴파일 시점에 미리 정해 두는 언어)라는 공통점이 있지만, 세부 규칙에서 차이가 납니다.

항목CJava
정수형 크기int는 시스템마다 다를 수 있음(대개 4바이트)int는 항상 4바이트로 고정
논리형별도 bool 타입이 표준에 없고 정수 0/비0으로 참·거짓 표현(C99부터 _Bool)boolean 타입이 별도로 존재하며 true/false만 가능
문자열char 배열 + null 문자(\0)로 끝을 표시String 클래스(객체)로 표현, 길이 정보를 자체적으로 가짐
나눗셈정수 나눗셈은 소수점 버림(7 / 2는 3)정수 나눗셈 규칙은 C와 동일(7 / 2는 3)
나머지 연산자%, 피연산자가 음수면 구현별 차이 주의%, 피연산자가 음수일 때 부호는 왼쪽 피연산자를 따름

자주 틀리는 점: “Java의 int도 시스템마다 크기가 다르다”고 착각하는 경우가 있습니다. C의 int는 시스템(컴파일러·아키텍처)에 따라 크기가 달라질 수 있지만, Java는 언어 명세 자체가 int를 항상 4바이트로 고정합니다. 이 차이는 “왜 Java가 플랫폼 독립적인 언어라 불리는가”의 근거 중 하나입니다.

산술 연산자(+, -, *, /, %)와 비교 연산자(==, !=, <, >)는 두 언어에서 표기가 같지만, 문자열 비교에서 결정적으로 갈립니다.

// C: 문자열 비교는 == 로 하면 안 된다 (주소 비교가 되어버림) char a[] = "hello"; char b[] = "hello"; if (a == b) { printf("같다\n"); } else { printf("다르다\n"); }
다르다

C에서 ab는 서로 다른 메모리 주소를 가리키는 배열이므로 a == b주소값을 비교해 항상 거짓이 됩니다. 문자열 내용을 비교하려면 strcmp(a, b) == 0을 써야 합니다.

// Java: 문자열 내용 비교는 equals(), == 는 참조(주소) 비교 String a = "hello"; String b = new String("hello"); System.out.println(a == b); System.out.println(a.equals(b));
false true

Java도 ==는 두 참조(reference, 객체가 있는 메모리 위치를 가리키는 값)가 같은 객체를 가리키는지 비교합니다. new String("hello")는 매번 새 객체를 만들기 때문에 a == b는 거짓이지만, 내용을 비교하는 equals 메서드는 참을 반환합니다. C의 문자열 비교 함정과 Java의 문자열 비교 함정이 사실상 같은 원리(주소 vs 내용)에서 나온다는 점이 통합프로그래밍이 두 언어를 나란히 물을 때 자주 노리는 지점입니다.

쉽게 말하면: C의 배열도, Java의 new로 만든 객체도 “이름이 같은 상자”일 뿐 “같은 상자”는 아닙니다. 내용물이 같은지는 내용물을 직접 열어 봐야 압니다(strcmp, equals).

2. 제어문 비교

조건문과 반복문의 기본 골격은 두 언어가 거의 동일합니다.

구조CJava
조건문if (조건) { } else { }if (조건) { } else { } (동일)
다중 분기switch (식) { case 값: ... break; }switch (식) { case 값: ... break; } (Java도 문자열 switch 가능)
전형 반복for (초기화; 조건; 증감) { }for (초기화; 조건; 증감) { } (동일)
컬렉션 순회표준에 없음(배열 인덱스로 직접 순회)확장 for문 for (자료형 변수 : 컬렉션) { } 지원
조건 반복while, do-whilewhile, do-while (동일)

Java의 확장 for문(향상된 for문이라고도 부르며, for-each라고도 부름)은 C에는 없는 문법입니다. 배열이나 컬렉션의 모든 원소를 인덱스 계산 없이 순회할 때 씁니다.

int[] scores = {90, 85, 77}; int total = 0; for (int s : scores) { total += s; } System.out.println(total);
252

3. 함수와 메서드 비교 — 실행 결과 추적 맛보기

C의 함수와 Java의 메서드는 이름은 다르지만 “입력을 받아 처리한 뒤 값을 돌려주는 코드 묶음”이라는 역할은 같습니다. 차이는 메서드가 반드시 클래스(class, 객체를 만들기 위한 설계도) 안에 속해야 한다는 점입니다. 여기서 통합프로그래밍의 대표 문항 유형인 코드 실행 결과 예측을 실제로 연습해 보겠습니다.

#include <stdio.h> int addOne(int x) { x = x + 1; return x; } int main(void) { int n = 5; int m = addOne(n); printf("%d %d\n", n, m); return 0; }

이 코드를 한 줄씩 추적하면 다음과 같습니다.

실행 내용nmx(addOne 내부)
int n = 5;n을 5로 초기화5
int m = addOne(n); 호출n의 값 5를 복사해 x에 전달(call by value, 값에 의한 호출)55
x = x + 1;x만 6으로 바뀜, n은 영향 없음56
return x;6을 반환, m에 대입56(함수 종료)
printf("%d %d\n", n, m);nm을 순서대로 출력56
5 6

자주 틀리는 점: addOne(n) 호출 이후 n도 6으로 바뀌었을 것이라 착각하는 경우가 매우 많습니다. C의 기본 인자 전달 방식은 값에 의한 호출(call by value)이라서, 함수 안의 xn의 값을 복사해 받은 별개의 변수입니다. x를 아무리 바꿔도 호출한 쪽의 n은 그대로입니다. 이 원리는 07편에서 포인터로 주소를 넘기는 방식(call by reference 유사 효과)과 대조하며 다시 다룹니다.

같은 원리를 Java 메서드로도 확인해 보겠습니다.

public class Main { static int addOne(int x) { x = x + 1; return x; } public static void main(String[] args) { int n = 5; int m = addOne(n); System.out.println(n + " " + m); } }
5 6

기본형(primitive type, int·double처럼 값 자체를 직접 담는 자료형)을 인자로 넘길 때 Java도 C와 똑같이 값을 복사해서 전달합니다. 즉 addOne 안에서 x를 바꿔도 mainn은 영향받지 않습니다. C의 값에 의한 호출과 Java 기본형의 값 전달이 같은 원리라는 점이 두 언어를 나란히 다루는 통합프로그래밍에서 반복적으로 등장하는 비교 포인트입니다.

쉽게 말하면: 함수(메서드)에 변수를 넘기는 것은 원본을 빌려주는 것이 아니라, 원본의 “사본”을 복사해서 건네는 것과 같습니다. 사본을 아무리 고쳐도 원본은 그대로입니다.

4. 독학사 스타일 문항 맛보기 ① — 빈칸 채우기

다음은 1부터 5까지의 합을 구하는 C 코드입니다. 빈칸에 들어갈 코드로 가장 적절한 것을 생각해 보세요.

#include <stdio.h> int main(void) { int sum = 0; int i; for (i = 1; i <= 5; i++) { sum = sum + ______; } printf("%d\n", sum); return 0; }

빈칸에 i가 들어가면 sum은 1+2+3+4+5, 즉 15가 됩니다. 만약 실수로 sum을 넣으면 반복마다 sum이 자기 자신을 계속 더해 기하급수적으로 커지는 전혀 다른 결과가 나옵니다. 빈칸 채우기 문항은 “반복문이 무엇을 누적하고 있는가”를 정확히 짚었는지 확인하는 유형입니다.

15

5. 독학사 스타일 문항 맛보기 ② — 실행 결과 예측

public class Main { public static void main(String[] args) { int a = 3; int b = 4; int c = a++ + ++b; System.out.println(a + " " + b + " " + c); } }

이 코드는 전위 증가(++b, 먼저 1 증가시킨 값을 사용)와 후위 증가(a++, 먼저 현재 값을 사용한 뒤 증가)가 한 줄에 섞여 있는 전형적인 함정 문제입니다. 한 줄씩 추적해 보겠습니다.

단계연산abc
초기값34
a++ 평가현재 값 3을 식에 사용한 뒤 a를 4로 증가44
++b 평가b를 먼저 5로 증가시킨 뒤 그 값을 식에 사용45
c = 3 + 5두 값을 더해 c에 대입458
4 5 8

자주 틀리는 점: a++++b를 모두 “증가한 뒤의 값”으로 계산해 c를 4+5=9로 착각하는 경우가 많습니다. 후위 증가 연산자는 식에는 증가 전 값을 넘기고, 증가 자체는 그 문장이 끝난 뒤에 반영된다는 점을 반드시 구분해야 합니다.

6. 독학사 스타일 문항 맛보기 ③ — 오류 찾기

다음 C 코드에는 컴파일 또는 실행 단계에서 문제가 되는 부분이 있습니다.

#include <stdio.h> int main(void) { int arr[5] = {1, 2, 3, 4, 5}; int i; for (i = 0; i <= 5; i++) { printf("%d\n", arr[i]); } return 0; }

이 코드의 문제는 반복 조건 i <= 5입니다. 배열 arr는 크기가 5이므로 유효한 인덱스는 0부터 4까지입니다. 그런데 조건이 i <= 5이면 i가 5일 때도 반복문이 실행되어 arr[5]에 접근하게 되는데, 이는 배열 경계를 벗어난 접근(out-of-bounds access, 배열이 실제로 확보한 메모리 범위 밖을 읽는 것)입니다. C는 이런 접근을 컴파일 시점에 막아 주지 않으며, 실행 시 예측할 수 없는 값을 출력하거나 프로그램이 비정상 종료될 수 있습니다.

1 2 3 4 5 (정의되지 않은 값 또는 오류 — 실행 환경마다 다름)

올바른 조건은 i < 5(또는 i <= 4)입니다. Java였다면 같은 실수를 저질러도 ArrayIndexOutOfBoundsException(배열 인덱스 범위를 벗어났을 때 Java 실행 환경이 즉시 발생시키는 예외)이 발생해 그 자리에서 바로 알아챌 수 있다는 차이가 있습니다. C는 경계를 벗어나도 조용히 잘못된 값을 돌려줄 수 있고, Java는 예외를 던져 즉시 알려 준다는 이 차이는 12편에서 예외 처리를 다룰 때 다시 연결됩니다.

쉽게 말하면: C의 배열은 “선을 넘어도 경고 없이 넘어가지는 위험한 통로”이고, Java의 배열은 “선을 넘으면 즉시 경보가 울리는 통로”입니다.

핵심 정리

  • C와 Java는 정적 타입 언어라는 공통점이 있지만, int 크기 고정 여부, 논리형 존재 여부, 문자열 표현 방식에서 차이가 있다.
  • 문자열 비교는 두 언어 모두 ==가 아니라 내용 비교 수단(C의 strcmp, Java의 equals)을 써야 한다는 공통 함정을 갖는다.
  • C의 함수 인자 전달과 Java 기본형 인자 전달은 모두 값에 의한 호출(call by value)이며, 함수(메서드) 안에서 매개변수를 바꿔도 호출한 쪽의 원본 변수는 바뀌지 않는다.
  • 통합프로그래밍의 대표 문항 유형은 빈칸 채우기, 실행 결과 예측, 오류 찾기 세 가지이며, 모두 코드를 한 줄씩 추적하는 습관이 정답률을 좌우한다.
  • 배열 경계를 벗어난 접근은 C에서는 조용히 잘못된 값을 낼 수 있고, Java에서는 예외를 던져 즉시 드러난다.

마무리 복습

문제 14지선다
C와 Java의 문자열 비교에 대한 설명으로 옳지 않은 것은?
문제 24지선다
다음 C 코드의 실행 결과로 옳은 것은?
int addOne(int x) {
  x = x + 1;
  return x;
}

int main(void) {
  int n = 5;
  int m = addOne(n);
  printf("%d %d", n, m);
}
문제 34지선다
다음 Java 코드의 실행 결과로 옳은 것은?
int a = 3;
int b = 4;
int c = a++ + ++b;
System.out.println(a + " " + b + " " + c);
문제 44지선다
다음 C 코드에서 발생할 수 있는 문제로 가장 적절한 것은?
int arr[5] = {1, 2, 3, 4, 5};
for (i = 0; i <= 5; i++) {
  printf("%d", arr[i]);
}
문제 54지선다
C와 Java의 배열 경계를 벗어난 접근에 대한 설명으로 가장 적절한 것은?
문제 64지선다
다음 C 코드의 실행 결과로 옳은 것은?
int scores = 0;
for (i = 1; i <= 5; i++) {
  scores = scores + i;
}
printf("%d", scores);

참고 자료

Last updated on