[아두이노] C 언어 비교문에서 == 사용 방법

C 언어 비교문에서 == 사용 방법

C 언어에서 '='는 assignment, 즉 변수에 값을 넣어줄 때 사용하고 '=='는 compare, 즉 앞과 뒤의 값이 같은가를 비교하기 위해 사용한다.

하지만 '=='는 코딩을 하다 보면 타이핑 실수로 '='를 하나 빼 먹는 실수를 범하기 쉬운데, 별거 아닌거 같은 실수가 아주 치명적인 결과를 가져올 수가 있다.

먼저 아래 코드를 보자.

void setup() {
  Serial.begin(115200);  
  pinMode(13, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    byte ch = Serial.read();
    if (ch == N'1') {
      digitalWrite(13, HIGH);
    } else {
      digitalWrite(13, LOW);
    }
  }
}


시리얼 포트로 글자를 입력 받아 '1'이면 아두이노에 있는 LED를 켜고, 그 이외 글자인 경우 LED를 꺼 주는 매우 단순한 코드이다.

sketch_jun20a___%25E1%2584%258B%25E1%258
이 부분에서 시리얼 포트에서 입력받은 글자가 '1'인지 비교하고 있다. 그런데 저기서 실수로 '='를 하나 빼 먹으면 어떻게 될까?

sketch_jun20a___%25E1%2584%258B%25E1%258

이렇게 해도 컴파일을 하면 아무 문제 없이 컴파일이 완료된다.

sketch_jun20a___%25E1%2584%258B%25E1%258

이 코드를 아두이노에 업로드해 실행을 하면 어떻게 될까?

원래대로라면 업로드가 완료되면 시리얼 모니터에서 '1'을 보내 줘야만 불이 켜지게 된다. 하지만 위의 코드가 업로드 되면 시리얼 모니터에서 어떤 글자를 보내건 무조건 불이 켜지고 그 이후에는 어떤 글자를 보내는가 상관 없이 불이 계속 켜저 있고 끌수가 없게 된다.

왜 이런 문제가 발생하는 것일까?

답은 맨 위에서 설명했던 것 처럼 '='와 '=='의 의미 차이 때문이다.

ch == N'1' 라고 하는 경우는 ch에 들어 있는 글자와 '1'라는 글자를 비교해 같으면 True, 다르면 False라는 값이 출력된다. 그래서 if 구문이 ch에 들어 있는 글자에 따라 불을 켜거나 끌 수 있게 된다.

그런데 ch = N'1' 의 경우는 ch에 어떤 글자가 들어 있는가는 상관 없이 ch에 '1'이라는 글자를 새로 넣어주라는 의미가 된다. 즉 시리얼 포트에서 어떤 글자가 들어왔는가는 그냥 무시되어 버리는 것이다. 게다가 C 언어에서 '=' (assignment)의 경우 무조건 결과값으로 True가 나오게 되기 때문에

if (ch = N'1') {
  digitalWrite(13, HIGH); 
} else {
  digitalWrite(13, LOW);
}

저 코드에서 시리얼 포트에서 받은 값과 상관 없이 항상 digitalWrite(13, HIGH); 만 실행되게 된다.

게다가 바둑이나 장기를 둘 때 자기는 못보지만 훈수를 두는 사람은 쉽게 묘수를 볼 수 있는것처럼 저런 실수는 코딩을 한 당사사는 찾지 못하는 경우가 많다. 실제 코드가 길어지면 심한 경우 디버깅을 한다고 몇일, 몇달동안 코드를 한줄 한줄 뒤져보면서도 저 실수가 눈에 안 들어온다.

sketch_jun20a___%25E1%2584%258B%25E1%258

이것이 원하는 동작을 하는 코드인데 두개를 보고 한눈에 차이점을 찾을 수 있는가?? 지금까지 구구절절히 설명을 했으니 쉽게 찾겠지만 만일 따로 설명 없이 두개의 스크린샷만 놓고 차이점을 찾으라고 한다면 쉽지 않을 것이다.

그래서 비교문을 쓸 때 순서를 바꿔 쓰라고 권장하는 것이다.

즉 if (ch == N'1') 대신 if ('1' == ch) 이렇게 쓰는 습관을 들이는 것이 좋다.

그럼 단지 순서만 바뀌 쓰는 것인데 뭐가 좋다는 것일까?

만일 둘 다 '='를 하나 빼먹었다고 생각을 해 보자.

if (ch ='1') 는 문법상 틀린 부분이 없기 때문에 정상적으로 컴파일이 완료되고 실행된다. 물론 동작은 원하는것과 다르겠지만...
하지만 if ('1' = ch) 는 C언어 문법 자체가 틀렸기 때문에 컴파일을 하면

sketch_jun20a___%25E1%2584%258B%25E1%258

이렇게 에러가 발생하기 때문에 바로 실수를 바로잡아 줄 수가 있게 된다.

* C언어 문법에서 '='로 변수에 값을 넣어주는 경우 변수 이름은 '='의 왼쪽에, 변수에 넣어 줄 값은 '='의 오른쪽에 와야만 한다. "lvalue required as left operand of assignment" 이 문구가 그게 잘못되었다고 알려주는 것이다.

바로 잘못된 부분을 수정하고 컴파일 하면 이제 정상적으로 동작하게 된다.

sketch_jun20a___%25E1%2584%258B%25E1%258

프로그래밍을 할 때 컴파일러가 에러를 내 주는건 해결하기도 훨씬 쉽다. 하지만 위와 같이 실수를 했는데도 불구하고 컴파일은 정상적으로 되지만 생각하는것과 다르게 동작하는걸 찾는건 훨씬 힘들기 때문에 코딩할 때 부터 그 가능성을 없애줄 수 있는 습관을 들여 놓는 것이 좋다.
0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
118 아두이노 ESP32 Analog Inputs (ADC) +4 icon 양재동메이커 02-12 15,985
117 아두이노 TIP : Serial의 Port가 Open 시점 확인 icon 양재동메이커 01-21 12,874
116 아두이노 ESP32 Boot Mode icon 양재동메이커 12-28 12,667
115 아두이노 아두이노 에러 리스트(Arduino Error list) icon 양재동메이커 11-24 17,602
114 아두이노 ESP32 main.cpp +1 icon 양재동메이커 11-19 13,038
113 아두이노 ESP32 EEPROM 와 IR Remote icon 양재동메이커 08-06 12,937
112 아두이노 Learn ESP32 icon 양재동메이커 06-25 12,509
111 라즈베리 파이 라즈베리 파이 (Raspberry Pi) 기초 icon 양재동메이커 06-19 13,954
110 라즈베리 파이 (동영상 강의) 라즈베리 파이 강좌 Link icon 양재동메이커 06-17 13,109
109 STM32 / MBED [MED] Switch debouncing icon HellMaker 12-30 15,052
108 기타 [타이젠] 아두이노의 16x2 LCD Display라이브러리 LiquidCrystal_I2C의 타이젠 포팅 icon 양재동메이커 09-15 14,657
107 기타 [타이젠] GPIO의 디지탈 출력과 입력 인터럽트의 C++ Class 제작 icon 양재동메이커 09-12 14,132
106 마이크로비트 서보 모터 icon HellMaker 09-03 13,969
105 마이크로비트 아날로그 온도센서 (마이크로 비트 센서 활용) icon HellMaker 09-01 14,474
104 마이크로비트 터치센서 (마이크로 비트 센서 활용) icon HellMaker 09-01 13,568
103 마이크로비트 디지털 홀 센서 (마이크로 비트 센서 활용) icon HellMaker 08-29 12,746
102 마이크로비트 리니어 홀 센서 (마이크로 비트 센서 활용) icon HellMaker 08-29 12,275
101 마이크로비트 불꽃 감지 센서 (마이크로 비트 센서 활용) icon HellMaker 08-26 12,631
100 마이크로비트 로터리 엔코더 (마이크로 비트 센서 활용) icon HellMaker 08-25 12,767
99 마이크로비트 2컬러 LED(3mm) (센서 활용) icon HellMaker 08-22 12,744