들여 쓰기 #defines


99

#defines 등은 일반적으로 들여 쓰기되지 않는다는 것을 알고 있습니다. 왜?

나는 현재 #defines, #ifdefs, #elses, #endifs 등 의 끔찍한 혼합이있는 일부 코드에서 작업하고 있습니다 .이 모든 것들은 종종 일반 C 코드와 섞여 있습니다. #defines를 들여 쓰지 않으면 읽기가 어렵습니다. 그리고 들여 쓰기 된 코드와 들여 쓰기되지 않은 #defines 의 혼합은 악몽입니다.

#defines를 들여 쓰지 않으면 어떤 이점이 있습니까? 들여 쓰기를하면 나쁜 사람이 되나요? 이게 훨씬 멋지지 않나요?

#ifdef SDCC
    #if DEBUGGING == 1
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x3DC0
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x7DC0
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #else
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x4000
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x8000
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #endif
#else
    #if DEBUGGING == 1
        #define FLASH_MEMORY_END 0x7DC0
    #else
        #define FLASH_MEMORY_END 0x8000
    #endif
#endif

답변:


103

ANSI C 이전 전처리 기는 줄의 시작과 "#"문자 사이에 공백을 허용하지 않았습니다. 선행 "#"은 항상 첫 번째 열에 배치되어야합니다.

현재 ANSI C 이전 컴파일러는 존재하지 않습니다. 선호하는 스타일 ( "#"앞의 공백 또는 "#"과 식별자 사이의 공백)을 사용하십시오.

http://www.delorie.com/gnu/docs/gcc/cpp_48.html


26

일부가 이미 말했듯이 일부 Pre-ANSI 컴파일러는 #을 줄의 첫 번째 문자로 요구했지만 de 전 처리기 지시문을 첨부 할 필요가 없었기 때문에 이러한 방식으로 들여 쓰기가 이루어졌습니다.

#ifdef SDCC
#  if DEBUGGING == 1
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x3DC0
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x7DC0
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  else
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x4000
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x8000
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  endif
#else
#  if DEBUGGING == 1
#    define FLASH_MEMORY_END 0x7DC0
#  else
#    define FLASH_MEMORY_END 0x8000
#  endif
#endif

나는 종종 오래된 유닉스 헤더에서이 스타일을 보았지만, 그런 코드에서는 구문 색상이 종종 실패하기 때문에 싫어합니다. 전 처리기 지시문에 매우 눈에 띄는 색상을 사용하여 눈에 띄도록합니다 (메타 수준이므로 정상적인 코드 흐름의 일부가되어서는 안됩니다). SO가 유용한 방식으로 시퀀스를 색칠하지 않는다는 것을 알 수도 있습니다.


16

전 처리기 지시문의 구문 분석과 관련하여 C99 표준 (및 그 이전의 C89 표준)은 컴파일러가 논리적으로 수행하는 작업 순서에 대해 명확했습니다. 특히 다음과 같은 코드를 의미한다고 생각합니다.

/* */ # /* */ include /* */ <stdio.h> /* */

다음과 같습니다.

#include <stdio.h>

좋든 나쁘 든 '-std = c89 -pedantic'을 사용하는 GCC 3.4.4는 어쨌든 주석이 담긴 라인을 허용합니다. 나는 그것을 스타일로 옹호하는 것이 아닙니다. 가능하다고 생각합니다.

ISO / IEC 9899 : 1999 섹션 5.1.1.2 번역 단계에서는 다음과 같이 말합니다.

  1. [삼중 문자를 포함한 문자 매핑]

  2. [줄 스 플라이 싱-백 슬래시 줄 바꿈 제거]

  3. 소스 파일은 사전 처리 토큰과 일련의 공백 문자 (주석 포함)로 분해됩니다. 소스 파일은 부분 전처리 토큰이나 부분 주석으로 끝나서는 안됩니다. 각 주석은 하나의 공백 문자로 대체됩니다. 개행 문자는 유지됩니다. 줄 바꾸기가 아닌 공백 문자의 비어 있지 않은 각 시퀀스가 ​​유지되거나 하나의 공백 문자로 대체되는지 여부는 구현에서 정의됩니다.

  4. 전처리 지시문이 실행되고 매크로 호출이 확장됩니다. [...]

섹션 6.10 전처리 지시문은 다음과 같이 말합니다.

전처리 지시문은 (번역 단계 4 시작시) 소스 파일의 첫 번째 문자 (선택적으로 줄 바꿈 문자가없는 공백 뒤)이거나 다음 중 하나 인 # 전처리 토큰으로 시작하는 일련의 전처리 토큰으로 구성됩니다. 하나 이상의 개행 문자를 포함하는 공백 뒤에 나오고 다음 개행 문자로 끝납니다.

가능한 유일한 논쟁은 '(번역 단계 4 시작시)'괄호 표현입니다. 이는 해시 앞의 주석이 4 단계가 끝날 때까지 공백으로 대체되지 않기 때문에 없어야 함을 의미 할 수 있습니다.

다른 사람들이 언급했듯이 사전 표준 C 전처리 기는 여러 방식으로 균일하게 작동하지 않았으며 전 처리기 지시문 앞뒤에 공백이있는 영역 중 하나는 앞에 공백이있는 전 처리기 지시문을 인식하지 않는 것을 포함하여 다른 컴파일러가 다른 작업을 수행하는 영역 중 하나였습니다. .

주석이 분석되기 전에 백 슬래시-개행 제거가 발생한다는 점은 주목할 만합니다. 따라서 //주석을 백 슬래시로 끝내면 안됩니다 .


7

왜 더 흔하지 않은지 모르겠습니다. 내가 전 처리기 지시문을 들여 쓰고 싶을 때가 확실히 있습니다.

내 방식을 계속 방해하는 한 가지 (때로는 시도를 중단하도록 설득하는 경우도 있음)는 많은 또는 대부분의 편집자 / IDE가 사소한 자극에도 1 열에 지시문을 던진다는 것입니다. 그것은 지옥처럼 성가시다.


5

요즘 나는 이것이 주로 스타일의 선택이라고 믿습니다. 나는 생각 먼 과거의 한 시점에서, 모든 컴파일러가 전 처리기 정의를 들여 쓰기의 개념을 지원. 나는 약간의 조사를했지만 그 주장을 뒷받침 할 수 없었다. 그러나 어쨌든 모든 최신 컴파일러는 전 처리기 매크로 들여 쓰기 아이디어를 지원하는 것으로 보입니다. 나는 C 또는 C ++ 표준의 사본이 없기 때문에 이것이 표준 동작인지 아닌지 알 수 없습니다.

좋은 스타일인지 아닌지. 개인적으로 나는 그것들을 모두 왼쪽에 두는 아이디어를 좋아합니다. 그것은 당신에게 그들을 찾을 수있는 일관된 장소를 제공합니다. 네, 매우 중첩 된 매크로가 있으면 짜증이 날 수 있습니다. 그러나 들여 쓰기를하면 결국 더 이상하게 보이는 코드로 끝날 것입니다.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif

14
이 코드가 이상하게 보이는 이유는 두 개의 들여 쓰기 "스트림"을 만들었 기 때문입니다. 4 행을 한 단계 더 들여 쓰기하고 6과 7 행을 두 단계 더 들여 쓰기합니다.
Kevin Laity

3
전적으로 동의합니다. 나는 때때로 중괄호를 넣어서 #if가 if와 똑같이 보이도록합니다.
baash05 2010 년

3
실제 코드가있는 부분에 줄 이 없도록 코드를 정렬하려고 매우 열심히 노력 #ifdef합니다. 대신, 조건부 물건이 필요하다면 그것을 인수 분해 함수에 넣거나 매크로를 제거했습니다. 내가 찾는 방식이 훨씬 더 명확합니다 (적어도 나에게는 그렇습니다). 이상적으로는 모든 부분이 다른 파일 (헤더 또는 조건부로 컴파일 된 소스 파일, 일반적인 "조건"은 코드가 빌드되는 플랫폼 임)에 있습니다.
Donal Fellows

2
4 행을 한 단계 들여 쓰기하고, 6 행과 7 행을 두 단계로 들여 씁니다.
Rocketmagnet

3

주어진 예의 경우, 중첩 된 지시문의 복잡한 구조가 있으므로 들여 쓰기를 사용하여 더 명확하게 만드는 것이 적절할 수 있습니다.

개인적으로 이러한 지시문은 나머지 코드와 별도로 작동하기 때문에 대부분의 경우 들여 쓰기를하지 않는 것이 유용하다고 생각합니다. #ifdef와 같은 지시문은 컴파일러가 코드를보기 전에 전처리기에 의해 처리되므로 #ifdef 지시문 이후의 코드 블록은 컴파일 되지 않을 수도 있습니다 .

지시문이 코드와 함께 분산되어있을 때 (당신이 제공하는 예에서와 같이 지시문의 전용 블록이 아니라) 시각적으로 나머지 코드와 분리 된 상태를 유지하는 것이 더 중요합니다.


3
IP의 관점에서 컴파일되지 않은 것과 jmp로 인해 도달하지 않은 것의 차이점은 무엇입니까?
baash05 2010 년

2

나는 현재 #defines, #ifdefs, #elses, #endifs, #etc의 끔찍한 혼합이있는 일부 코드에서 작업하고 있습니다. 이 모든 것은 종종 일반 C 코드와 섞여 있습니다. #defines의 들여 쓰기가 없으면 읽기가 어렵습니다. 그리고 들여 쓰기 된 코드와 들여 쓰기되지 않은 #defines의 혼합은 악몽입니다.

일반적인 해결책은 지시문에 주석을 달아 지시문이 참조하는 내용을 쉽게 알 수 있도록하는 것입니다.

#ifdef FOO
/* a lot of code */
#endif /* FOO */

#ifndef FOO
/* a lot of code */
#endif /* not FOO */

6
나는 그 스타일을 보았고, 내 상사가 그것을 사용합니다. 그리고 나머지 코드와 마찬가지로 엉망이됩니다. 일반적인 if () 문에서 들여 쓰기를 모두 제거하고 대신 해당 주석을 사용한다고 상상해보십시오. 그들이 말하는 것을 쉽게 볼 수 없다고 불평 할 것입니다.
Rocketmagnet

2

현재 사용 가능한 거의 모든 C / CPP 컴파일러에서 제한되지 않습니다. 코드를 정렬하는 방법은 사용자가 결정합니다. 정말 행복한 코딩입니다.


1
괜찮은 대답. 특정 스타일 가이드 참조를 추가하여 개선 할 수 있습니까?
EtherDragon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.