본문 바로가기
  • 오늘도 신나게
코딩을 합시다/최대한 쉽게 설명한 C 언어

초등학생도 이해하는 C 언어 - & 와 && 의 차이점

by 앵그리선반장 2020. 5. 23.

C 언어를 처음 접하고 코딩을 시작하면 상당히 헷갈리는 부분이 생깁니다.
그 대표적인 예가바로  & 와 &&  그리고 | 와 || 입니다.
둘 다 AND 와 OR 연산임은 맞는데 뭐가 다를까요?

먼저 & 와 |비트 연산자이고,
&& 와 ||논리 연산자입니다.

정확히 설명을 하자면,
& 는 특정 변수를 각 비트별로 AND 연산을 하여 그 값을 도출해 내는 것이고,
&& 는 변수의 값 자체의 논리 값을 AND 연산해 결과 값 또한 논리 값으로 표현 됩니다.

따라서 비트 연산과 논리 연산은 그 용도가 다릅니다.
& 는 비트단위로 사칙연산과 같은 값의 계산을 위해 사용되고,
&& 는 True / False 를 구분 하기 위해 사용됩니다.

먼저 비트연산을 알아보겠습니다.
비트 연산을 이해 하기 위해서는 비트가 무엇인지 알아야 겠지요.
비트는 데이터를 저장 할 수 있는 최소의 단위 입니다.
저장한다는 것은 컴퓨터가 메모리에 데이터를 기억 한다는 뜻이며, 그 데이터의 형태를 0 과 1 로만 표현 했다는 겁니다.
그럼 0 과 1을 메모리에 어떻게 적을까요? 연필로 쓰지는 않겠지요?
바로 전기가 통하는 상태와 전기가 통하지 않는 상태를 각각 1 과 0 으로 정의 합니다.
정확히는 특정 전압 이상( 메모리마다 다르며 메모리를 구성하는 래치의 상태를 High 상태로 만들 수 있는 트랜지스터 베이스단자의 입력 전압) 일때를 1, 그 이하일때를 0 이라 정의 합니다.

그렇다면, 0 과 1 만으로 어떻게 숫자 5를 표현 할까요?
이것을 이해하기위해 '진수법' 을 알아야 합니다.
0 과 1 만 가지고 데이터를 표현 하는 방법을 '2진법'이라고 합니다.
그럼 우리가 흔히 쓰는 숫자의 진수법은 무엇일까요? 
바로 10진법 입니다.
먼저 2 진법으로 숫자 0~ 3 까지 표현을 시도해 보겠습니다.

2 진법 10 진법
0 0
1 1
? 2

숫자 3을 표현 할 수 가 없군요.
이래서 1 비트로는 2가지의 데이터면 표현 할 수 있습니다.

그렇다면 그 이상의 데이터는 어떻게 표한 할까요?
바로 비트를 연결해서 사용 하면 됩니다.

2 진법  10진법
00 0
01 1
10 2
11 3
?? 4

두 개의 비트를 연결해 데이터를 표현 했더니 10 진수의 0~3 까지 총 4 개의 값을 표현 할 수 있습니다.
그렇다면 이 비트의 수가 많아질 수록 표현 가능한 숫자의 크기도 달라지겠지요.

2 진법 10 진법
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
...  
1111 15

 4비트 데이터로 표현 가능한 숫자는 0~15 까지 이고, 그 갯수가 16개입니다.

그런데 여기서 한 가지 문제가 있습니다.
바로 2 진법으로 표현된 숫자는 10 진법으로 쉽게 파악되지 않는다는 것입니다.
하지만 아래 표와 같이 16진법을 사용하면 비트(2진법)으로 표현된 데이터의 가독성이 매우 높아집니다.

2 진법  16 진법  10 진법
0000 0000 0x00 0
0000 0001 0x01 1
0000 0010 0x02 2
0000 0011 0x03 3
0000 0100 0x04 4
0000 0101 0x05 5
0000 0110 0x06 6
0000 0111 0x07 7
0000 1000 0x08 8
0000 1001 0x09 9
0000 1010 0x0A 10
0000 1011 0x0B 11
0000 1100 0x0C 12
0000 1101 0x0D 13
0000 1110 0x0E 14
0000 1111 0x0F 15
0001 0000 0x10 16
0001 0001 0x11 17
0001 0010 0x12 18
0001 0011 0x13 19
0001 0100 0x14 20
. . . . . . . . .

참고 : 16 진수 앞에 붙은 "0x" 는 16 진수 임을 나타내는 표시 입니다.
위 그림과 같이 2 진수를 16진수로 표현 했을때 자리 올림의 형태가 4비트 단위로 맞아떨어져 매우 가독성이 좋습니다.
따라서 컴퓨팅의 모든 데이터는 2 진수로 저장되고, 계산은 16진수로 표현합니다.

어쨌든, 
비트연산은 이처럼 몇 개의 비트로 구성된 데이터를 서로 더하거나 빼거나 반전 시키는 등의 연산을 하는 것을 말합니다.
그중 & 는 이 비트들을 자릿수별로 곱한 것과 같습니다.
연산 기호 & 는 논리 연산 게이트 AND 와 같은 계산입니다.,
예를들어 다음 코드를 보겠습니다.

#include  <stdio.h>

void main(void)
{
    int a, b, c;
    a = 0x0A;
    b = 0x0E;
    c = 0;

    c = a&b;  
    printf("c = %d[0x%x]\n",c,c);
}

위 코드의 결과는 아래와 같습니다.

c = 10[0xa]

이것은 실제 회로적으로 아래 그림과 같은 로직을 거치게 됩니다.
변수 a 에 저장된 값 0x0A 는 2 진수로 1010 이고, 
변수 b 에 저장된 값 0x0E 는 2 진수로 1110 입니다.
이 두 변수를 & 연산 하게 되면 각 비트별로 AND 게이트를 거치게 됩니다.

각 비트별 AND 게이트를 거친 값은 비트 값으로 1010 이며, 16 진수로 0x0A 가 됩니다.
이처럼 & 연산을 하게되면 한 가지 특징이 있습니다.
바로 앞에 나온 변수의 비트값이 0 이면 다음에 오는 값의 비트가 무엇이든 무조건 0 이 되며,
앞 변수의 비트값이 1 일때 다음 변수의 비트값에 따라 그 값이 결정되게 된다는 것 입니다.
따라서 이런 연산은 이미지처리에서 필터링으로도 활용 될 수 있습니다.

다음은  && 연산에 대해 알아보겠습니다.
앞서 말했듯이 && 는 논리 연산자 입니다.
주어진 두개의 변수의 논리값의 AND 연산인 것 입니다.
이해를 돕기위해 소스코드를 먼저 보겠습니다.

#include  <stdio.h>

int main(void)
{
    int a, b, c;
    a = 0x0A;
    b = 0x0E;
    c = 0;

    c = a&&b;  
    printf("c = %d[0x%x]\n",c,c);
    return 0;
}

앞선 & 예제의 코드에서  c=a&b  를 c = a&&b 로만 바꿨습니다.
결과는 아래와 같습니다.

c = 1[0x1]

값이 1 이 나왔습니다.
계산된 값 (0x0A) 가 아닌 논리값 1 이 나온 것입니다.

이것이 실제로 어떤 로직을 거쳤는지 그림으로 살펴 보겠습니다.

이처럼, 값 자체를 계산하지 않고, 각 값의 논리 값을 연산하여 그 결과 또한 논리 값으로 표현한 것 입니다.

만약 변수 A 또는 B 의 값이 0 이면 False 가 나올 것입니다.

논리 값은 0이 아닌 모든 숫자가 1(True) 임을 알아야 합니다.)
즉 -1 도 True 입니다.
간혹 0보다 작은 숫자를 False 로 착각 하는 경우가 있는데요. 0 이 아니면 True 입니다.
따라서 

-1 & 1 = 1   이라는 것을 유념 하시기 바랍니다.

| 와 ||   (or ) 는 설명하지 않겠습니다.
단지 AND 연산이 OR 연산으로 바뀐것일 뿐 원리는 같습니다.

댓글