C언어

[ !!의 쓰임 ] What is "!!" in C?

Jueun Park 2021. 1. 19. 18:18

!과 !!의 의미

A = 사과는 영어로 Apple이다.
B = 신형 맥북프로의 공홈 가격은 10만원이다.

A -> TRUE -> 1
B -> FALSE -> 0

!A -> !(TRUE) -> FALSE -> 0
!B -> !(FALSE) -> TRUE -> 1

!!A -> !(!(TRUE)) -> !(FALSE) -> TRUE -> 1
!!B -> !(!(FALSE)) -> !(TRUE) -> FALSE -> 0

쉽게 생각하면 3이나 4.5 같은 것을 1로 쉽게 바꿀 수 있는 표현이다.

반환값이 char* 이거나 0, 1이 아닌 int를 반환하는 경우 유용할 거 같다.
아래는 양수 혹은 0, 음수를 반환하는 함수를 이용해서
1이상의 수를 반환하는 경우에 I++을 해주려는 경우이다.

i += (has_newline(target) > 0);
//7이 반환되었다고 했을때, 7은 0보다 크니까 괄호가 TRUE가 되어, i에 +1이 된다.

이런식으로 짤 수도 있고

i += !!has_newline(target);
//7이 반환되었다고 했을때, !7은 0이고 !0은 1이기 때문에 i에 1이 더해진다. 

이런식으로 짤 수도 있다.

!을 사용한 코드

!을 사용하면 코드를 효율적으로 짤 수 있다.

    fd = open("./test.txt", O_RDONLY);
    if (!fd)                //open -> 정상으로 open했다면 파일 디스크립터의 양의 정수 값. 실패하면 -1 반환
        return (-1);    //실패시 -1 리턴하고 프로그램 종료.

아래는vi txt의 문장을 5글자씩 읽어오는 프로그램이다.
읽어온 5글자에 '\n'이 포함되어있으면 프로그램을 종료한다.
(한문장만 읽겠다는 뜻)

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int     has_newline(const char *s)        //buffer에 newline이 들어있는지 확인 하는 함수
{
    while (*s)
    {
        if (*s == '\n')
            return (1);
        s++;
    }
    return (0);
}

int main()
{
    char    *buf;
    int     newline;
    int     result;
    int     fd;

    fd = open("./test.txt", O_RDONLY);
    if (!fd)
        return (-1);
    result = read(3, buf, 5);        //while문에 들어가기 전에 한 번 읽는다. 여기서 결과가 0(문장의 끝)이나 -1(에러)로 나올경우에는 while문에 들어가지 않음
    while (result > 0 && !newline)
    {
        printf("%s\n", buf);        //출력
        result = read(3, buf, 5);    //5글자씩, 파일에서 읽어옴
        newline = has_newline(buf);    //newline이 있는지 체크
    }
    if (result >= 0)
        printf("%s\n", buf);
}

!!을 사용한 코드

위에서 봤던 코드에서, has_newline이라는 함수가
숫자가 아닌 char* 를 반환한다고 바꿔보자.

[ Changed ]
-has_newline의 return 값 자료형(int -> char*)

그런데 어떤 이유로 newline이 자료형을 int에서 char* 로 바꿀 수 없는 상황이다.
int 자료형인 newline에 has_newline의 반환값을 받으려면 어떻게 해야할까?

[정답]

          newline = !!has_newline(buf);

이렇게 해주면 (NULL)이 반환되면 숫자 0으로,
문자를 가리키고 있는 char * 가 반환되면 숫자 1로 바뀌어서 newline에 저장된다.

!! 출처: 스택오버플로우
open 반환값 출처

* 오타를 찾아준 Taehokim과 Heom 감사합니다. ✉️