ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C언어/Day2] C언어 수업정리 (정보처리기사, 실기) / 자바스크립트와 산술연산 결과가 다르게 나오는 이유
    Backend 2019. 5. 13. 12:11

    1. 산술연산자 / 증감연산자

    #include<stdio.h>
    int main() {
    	int num5 = 3, num6 = 3, num7 = 3, num8 = 3;
    
    	num5++; // ++num5; num5=num5+1; num5+=1;
    	printf("num5= %d \n", num5);
    
    	++num6; // num6++; num6=num6+1; num6+=1;
    	printf("num6= %d \n", num6);
    
    	num7--; // --num7; num7=num7-1; num7-=1;
    	printf("num7= %d \n", num7);
    
    	--num8; // num8--; num8=num8-1; num8-=1;
    	printf("num8= %d \n", num8);
    	
    	system("pause");
    	return 0;
    }

    실행결과

     

    자바스크립트에서도 공부했던 내용인데,

    똑같은 원리이지만 자바스크립트와 C언어가 약간 다르게 동작한다.

     

    #include<stdio.h>
    int main() {
    	int c, d, e, f;
    	int num1, num2, num3, num4;
    	num1 = num2 = num3 = num4 = 3;
    
    	c = num1++;  // c=num1; num1=num1+1;
    	// num1++; ++num1; num1=num1+1; num1+=1;
    	printf("c= %d, num1= %d \n", c, num1);
        
    	d = ++num2;  // num2=num2+1; d=num2;
    	printf("d= %d, num2= %d \n", d, num2);
    
    	system("pause");
    	return 0;
    }

    먼저 기본적인 내용을 정리해보자면 

    c = num1++; 이렇게 ++이 num1 뒤에 붙으면 증감연산을 하기 전에

    c에 num1을 대입한 후, num++을 뒤에 계산한다.

     

    그러므로 위에서 c와 num1을 print하면 c = 3, num1 = 4가 찍힌다.

     

    반면에 d = ++num2; 이렇게 ++이 num2 앞에 붙으면

    증감연산을 먼저 하고 계산한 값을 d에 대입한다.

     

    그러므로 d와 num2를 print하면 d = 4, num2 = 4가 된다.

     

    실행결과

     

    이 부분의 동작원리는 자바스크립트와 같다.

    var num1 = 3;
    var c = num1++;
    
    console.log(c, num1);	// 3 4
    
    var num2 = 3;
    var d = ++num2;
    
    console.log(d, num2);   // 4 4

     

    그러나 아래의 코드를 살펴보자.

    #include<stdio.h>
    int main() {
    	int e, f;
    	int num3 = 3, num4 = 3;
    
    	e = ++num3 + ++num3 + ++num3;	// num3 = 6 -> 6+6+6 = 18
    	printf("num3=%d, e=%d  \n", num3, e);	// num3 = 6, e = 18
    
    	f = num4++ + ++num4 + num4++;	// num4 = 4 -> 4+4+4 = 12
    	printf("num4=%d, f=%d \n", num4, f);	// num4 = 6, f = 12
    
    	system("pause");
    	return 0;
    }

    으엥? 자바스크립트만 공부하던 나에게 정말 생각치도 못한 결과가 나왔다.

    num3 = 6 / e = 18

    num4 = 6 / f = 12

     

    그럼 자바스크립트에서는 어떻게 동작할까?

    var num3 = 3. num4 = 3;
    var e = ++num3 + ++num3 + ++num3;
    console.log(num3, e); // 6 15
    
    var f = num4++ + ++num4 + num4++;
    console.log(num4, f); // 6 13

    num3 = 6 / e = 15

    num4 = 6 / f = 13

     

     

    이렇게 C언어와 자바스크립트에서 결과값이 다르게 나오는 이유는

    C언어는 컴파일러 랭귀지이고 자바스크립트는 인터프리터 랭귀지이기 때문이다.

    C언어는 코드를 작성한 다음 컴파일러를 사용하여 프로그램 전체를 목적 프로그램으로 번역한 후

    링킹 작업을 통해 실행 가능한 프로그램을 새롭게 생성한다.

     

    비쥬얼 스튜디오에서 간단한 C언어 예제 프로그램을 작성하고, 그것을 출력하려고 했을 때

    그냥 파일을 실행시키지 못하고 Ctrl Shift B를 눌러서 [솔루션 빌드]를 하고 실행시키는 것을 떠올릴 수 있다.

     

    이러한 C언어는 대표적인 정적 타입(Static/Strong Type) 언어로 프로그램이 실행될 때 이미 해당 메모리의 크기가 결정되는 언어이다. 우리 컴퓨터에 값을 저장하기 위해 메모리 공간을 우선적으로 확보해야 하는데, 이 메모리 공간의 크기는 데이터의 Type에 의해 결정된다. C나 Java같은 정적 타입 언어는 변수를 선언할 때 변수 타입을 미리 지정해야 한다.

    // 1byte 정수형: -128 ~ 127
    char c;
    
    // 4byte 정수형: -2,124,483,648 ~ 2,124,483,647
    int num;

     

     

    그러나 자바스크립트는 C언어와 다르게 프로그램을 실행하는 즉시 위에서부터 한 줄씩 번역하며 바로 바로 실행하는 인터프리터 언어이다. 

    자바스크립트는 동적 타입(Dynamic/Weak Type)언어로 사전에 데이터 타입이 미리 결정되는 것이 아니고 값이 할당되는 도중에 자동으로 변수의 타입이 결정된다. 따라서 var라는 변수에 string type, number type, object type 등등 다양한 타입의 값을 자유롭게 할당할 수 있다.

    var a = "string";
    var b = 123;
    var c = function foo () {};

     

     

    이제 아까의 코드를 다시 살펴보자.

    #include<stdio.h>
    int main() {
    	int e, f;
    	int num3 = 3, num4 = 3;
    
    	e = ++num3 + ++num3 + ++num3;	// num3 = 6 -> 6+6+6 = 18
    	printf("num3=%d, e=%d  \n", num3, e);	// num3 = 6, e = 18
    
    	f = num4++ + ++num4 + num4++;	// num4 = 4 -> 4+4+4 = 12
    	printf("num4=%d, f=%d \n", num4, f);	// num4 = 6, f = 12
    
    	system("pause");
    	return 0;
    }

     

    e = ++num3 + ++num3 + ++num3;

    여기서 ++num3가 먼저 계산된다. 3에 1을 바로 증가시켜 4가 된다.

    ++num3가 그 다음에 계산된다. 4에 1을 증가시켜 5가 된다.

    ++num3가 그 다음에 계산된다. 5에 1을 증가시켜 6이 된다. (num3 = 6 결정됨.)

     

    이제 이 3가지 값을 더하는 데, C언어에서는 이미 증가되어 6이 된 값을 3번 더하는 셈이 되므로

    e = 6 + 6 + 6;이 되어 18이 된다.

     

    그러니까 num3를 3번 증감시킨 후 6이 된 num3를 세 번 더하여 e에 할당한다.

     

     

    f = num4++ + ++num4 + num4++;

    여기서 num4++가 계산된다. ++가 뒤에 있으므로 여전히 3이다.

    ++num4로 넘어가는 순간 num4는 4가 된다.

    num4++로 넘어가면 ++가 뒤에 있으므로 여전히 4이다.

    이렇게 계산이 끝난 후, 3개를 더하는 데 num4는 4이므로 

    f = 4 + 4 + 4;가 되어 12가 된다.

     

    그러니까 num4를 증감시키고 난 후 가장 마지막 값이 num4의 값이 되고 

    그 값을 3번 더하여 f에 할당하는 것이다.

     

     

    var num3 = 3. num4 = 3;
    var e = ++num3 + ++num3 + ++num3;
    console.log(num3, e); // 6 15
    
    var f = num4++ + ++num4 + num4++;
    console.log(num4, f); // 6 13

    자바스크립트에서는 이렇게 실행된다.

     

    e = ++num3 + ++num3 + ++num3;

    여기서 ++num3가 계산되어 4가 된다.

    ++num3가 또 계산되어 5가 된다. 

    ++num4가 또 계산되어 6이 된다.

     

    e는 마지막 값인 6을 3번 더하는 것이 아니고

    그 때 그 때 바뀐 num3의 값을 더한다.

     

    즉, e = 4 + 5 + 6 = 15;

     

     

    f = num4++ + ++num4 + num4++;

    먼저 num4++가 계산되는 데, 3이지만 ++num4로 넘어가는 순간 4로 변한다.

    4가 된 num4는 ++num4를 만나는 순간 5가 된다.

    num4++을 만나는 순간 여전히 5이지만 이 문장을 빠져나가는 순간

    num4는 6으로 바뀌므로 num4는 6이다.

     

    f는 처음에 num4가 ++num4를 만나기 전 3이었으므로 3을 기억한다.

    ++num4를 만나는 순간 5가 되었으므로 5를 저장한다.

    num4++으로 넘어가는 순간 여전히 num4는 5이다.

    이 문장을 빠져나가기 전이므로 f = 3 + 5 + 5;가 되어 13이 f에 할당된다.

     

     

    C언어와 다른 차이점이 바로 느껴진다.

    자바스크립트는 한 줄 실행할 때마다 변화하는 값을 바로 바로 반영하여 연산하기 때문에

    C언어보다 훨씬 더 혼동하기 쉬운 언어라고 느껴진다.

     

     

    2. 관계 연산자

    #include<stdio.h>
    int main(void) {
    	int num1 = 2, num2 = 4;
    	int result1, result2, result3, result4;
    
    	result1 = (num1 > num2);
    	result2 = (num1 <= num2);
    	result3 = (num1 == num2);
    	result4 = (num1 != num2);
    
    	printf("num1:2 > num2:4  %d \n", result1);	// 0(거짓)
    	printf("num1:2 <= num2:4   %d \n", result2);	// 1(참)
    	printf("num1:2 == num2:4   %d \n", result3);	// 0(거짓)
    	printf("num1:2 != num2:4   %d \n", result4);	// 1(참)
    
    	system("pause");
    	return 0;
    }

    관계 연산자는 간단하다. >, <, >=, <=, ==, != 등이 존재한다.

    0은 거짓이고 1은 참이다.

     

     

    3. 관계 논리 연산자

    #include<stdio.h>
    int main(void) {
    	int num1 = 2, num2 = 3, num3 = 5;
    	int result1, result2, result3, result4, result5;
    
    	result1 = (num1 > 0) && (num2 < 10);
    	result2 = (num2 <= 2) || (num3 > 5);  // binary(이항, 다항연산자)
    	result3 = !num3; // unary(단항연산자)
    
    	printf("(num1:2 > 0) && (num2:3 < 10) = %d \n", result1);  // 1(참)
    	printf("(num2:3 <= 2) || (num3:5 > 5) = %d \n", result2);  // 0(거짓)
    	printf("!num3 = %d \n", result3);  // 0(거짓)
    
    	system("pause");
    	return 0;
    }

    &&은 and연산자로 왼쪽, 오른쪽이 모두 참이어야 true이다.

    우리 컴퓨터는 조금이라도 연산을 빠르게 수행하기 위해

    &&연산을 했을 때, 만약에 왼쪽이 거짓인 경우, 오른쪽은 아예 검사하지 않고 거짓으로 판단한다.

     

    ||연산은 or연산자로 왼쪽 항과 오른쪽 항 둘 중에 하나라도 참인 경우에 true로 판별한다.

    만약에 왼쪽 항이 참인 경우, 오른쪽 항은 검사하지 않고 바로 참으로 판단한다.

     

     

    4. 비트 연산자

    #include<stdio.h>
    int main(void) {
    	int num1 = 2, num2 = 3, num3 = 5;
    	int result1, result2, result3, result4, result5;
    
    	// bit연산자
    	result4 = num1 & num2;
    	result5 = num1 | num2;
    
    	printf("num1:2 & num2:3 = %d \n", result4);  // 2
    	printf("num1:2 | num2:3 = %d \n", result5);  // 3
    
    	system("pause");
    	return 0;
    }

    &와 |는 비트 연산자이다.

     

    2과 3의 비트 연산을 표현해보면 다음과 같다.

     

    2 & 3 = 2

      128 64 32 16 8 4 2 1
    2진수 2 0 0 0 0 0 0 1 0
    2진수 3 0 0 0 0 0 0 1 1
    & 0 0 0 0 0 0 1 0

    and연산 시 둘 중에 하나라도 0이면 0이 나오고 두 개 다 1이어야 1이므로 

    연산 결과는 00000010 -> 2가 된다.

     

     

    2 | 3 = 3

      128 64 32 16 8 4 2 1
    2진수 2 0 0 0 0 0 0 1 0
    2진수 3 0 0 0 0 0 0 1 1
    | 0 0 0 0 0 0 1 1

    or연산 시 둘 중에 하나라도 1이면 1이 나오기 때문에

    연산 결과는 00000011 -> 3이 된다.

     

     


    참고 사이트 : 

    https://poiemaweb.com/js-data-type-variable

     

    Data type & Variable | PoiemaWeb

    변수는 값의 위치(주소)를 기억하는 저장소이다. 값의 위치란 값이 위치하고 있는 메모리 상의 주소(address)를 의미한다. 즉, 변수란 값이 위치하고 있는 메모리 주소(Memory address)에 접근하기 위해 사람이 이해할 수 있는 언어로 명명한 식별자(identifier)이다.

    poiemaweb.com

     

    반응형

    COMMENT