클랜 포맷이 내 코드를 깨뜨릴 수 있습니까?
~하듯이clang-format
코드를 다시 포맷하기 위한 도구인데, 이러한 포맷이 작동 코드를 깨거나 최소한 작동 방식을 변경할 수 있습니까?코드의 작동 방식을 바꿀 수 없는 어떤 종류의 계약이 있습니까?
는 가 많습니다.clang-format
줄들이 이라는 것을 의미합니다 이것은 코드의 많은 줄이 바뀔 것이라는 것을 의미합니다.A로가 없습니다.clang-format
이 프로세스를 크게 단순화할 수 있습니다.
저는 그렇게 말할 거예요.clang-format
코드의 작동 방식은 변경되지 않습니다.그러나 이것이 보장될 수 있을지 100% 확신할 수는 없습니다.
단답: 예.
clang-format
도구가 있습니다.-sort-includes
선택. 순서 #include
명령어는 기존 코드의 동작을 확실히 바꿀 수 있고, 기존 코드를 깰 수도 있습니다.
SortIncludes
옵션이 다음으로 설정됩니다.true
몇가지 된 스타일로 해,도 있습니다.clang-format
포함 항목을 다시 정렬할 것입니다.
마이 스트럭트.h:
struct MyStruct {
uint8_t value;
};
원본.c:
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
이제 우리가 도망간다고 치자.clang-format -style=llvm original.c > restyled.c
.
restyled.c:
#include "MyStruct.h"
#include <stddef.h>
#include <stdint.h>
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
합니다 시 과 같은 합니다.restyled.c
:
In file included from restyled.c:1:
./MyStruct.h:2:5: error: unknown type name 'uint8_t'
uint8_t value;
^
1 error generated.
그러나 이 문제는 쉽게 해결할 수 있어야 합니다.만,다 등 할 수 clang-format
합니다 합니다.#include
#include
사이사이의 선
고정 원본.c:
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
고정 스타일 .c:
#include <stddef.h>
#include <stdint.h>
#include "MyStruct.h"
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
:stdint.h
그리고.stddef.h
이 이기 때문에 빈 줄로 히 d"되었지만,되었습니다.MyStruct.h
표준 라이브러리가 다음을 포함하기 전에 이동되는 것으로부터.
하지만..
#include
명령어는 코드를 파괴합니다. 어쨌든 다음 중 하나를 수행해야 합니다.
헤더 파일의 각 헤더에 대한 종속성을 명시적으로 포함합니다.제 예를 들어, 저는 다음과 같은 것을 포함해야 합니다.
stdint.h
인에MyStruct.h
.포함 그룹 사이에 주문 종속성을 명시적으로 나타내는 주석 줄을 추가합니다.하세요가 아닌 사람은비...
#include
라인은 그룹을 분할해야 하므로 댓글 라인도 작동합니다.줄합니다를 합니다.clang-format
…을MyStruct.h
표준 라이브러리 헤더 앞에 표시됩니다.
대체-original.c:
#include <stdint.h>
#include <stddef.h>
// must come after stdint.h
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
확실히 코드가 작동하는 방식을 바꿀 수 있습니다.그리고 그 이유는 C 프로그램이 소스 코드의 일부 속성을 볼 수 있기 때문입니다.하고 있는 은입니다.__LINE__
매크로, 하지만 다른 방법이 있을지 모르겠네요.
.1.c
:
#include <stdio.h>
int main(){printf("%d\n", __LINE__);}
그러면:
> clang 1.c -o 1.exe & 1.exe
2
요 좀 .clang-format
:
> clang-format -style=Chromium 1.c >2.c
그리고.2.c
다음과 같습니다.
#include <stdio.h>
int main() {
printf("%d\n", __LINE__);
}
물론 출력도 변했습니다.
> clang 2.c -o 2.exe & 2.exe
3
부터.clang-format
는 을 미치므로다 할 수 .clang-format
ing은 공백까지 동일합니다.B리눅스/B에서 SD에서는한 SD/OS X를 할 수 .diff
그리고.tr
다음의 경우:
$ diff --ignore-all-space <(tr '\n' ' ' < 2.c ) <(tr '\n' ' ' < 1.c)
1.c:
#include <stdio.h>
int main() {printf("Hello, world!\n"); return 0;}
2.c:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
diff
다. 이는 파일을 의미합니다.1.c
그리고.2.c
공백까지 동일합니다.
Karoly가 그의 코멘트에서 언급했듯이, 이상적인 조건에서는 문자열 리터럴과 같이 여전히 중요한 공간을 확인해야 합니다.하지만 현실 세계에서는 이 시험이 충분하다고 생각합니다.
프로젝트에서 재포맷된 ASM 코드를 클랜 형식으로 변경한 것은 다음과 같은 효과적인 작업을 수행했기 때문입니다.
#define ASM _asm
ASM {
...
}
네.
작업 흐름을 끊지 않을 것입니다.
시스템에 "C_Cpp.clang_format_sortIncludes"라는 구성 스위치가 있습니다. false. 그러나 작동하지 않습니다. 무엇이 문제인지 모르겠습니다.
버전은:ms-vscode.cpptools-0.13.1입니다.
이것이 제 해결책입니다.
안정적인 작업 흐름을 위해 문법을 사용합니다.
// 철썩철썩 떨어지다
...여기 당신의 코드가 있습니다.
// 에 딱 달라붙는.
코드와 서식 설정에 특수 구문을 사용하면 코드가 끊어질 수 있습니다.
인라인 어셈블러
일반적으로 gcc로 코드를 컴파일하고 gcc 스타일 인라인 어셈블러를 사용한다면, clang-format은 %-문자를 연산자로 보기 때문에 레지스터 변수의 이름을 깰 가능성이 매우 높습니다.
asm_movq(%[val2], %%mm0)
로 다시 포맷됩니다.
asm_movq(% [val2], % % mm0)
더 이상 컴파일할 수 없습니다.
매크로에서 경로 구성
문자열을 사용하지 않고 매크로를 사용하여 경로를 구축하면 clang-format은 다시 '/' 문자를 연산자로 보고 그 주위에 공백을 둡니다.
예를 들어, 부스트는 다음과 같은 컨스트럭트를 사용합니다.
# define AUX778076_PREPROCESSED_HEADER \
BOOST_MPL_CFG_COMPILER_DIR/BOOST_MPL_PREPROCESSED_HEADER
헤더 파일에 대한 경로를 구성합니다.'/'은(는) 여기서 연산자가 아니지만 문자열 안에 없기 때문에 clang-format은 연산자로 취급하고 그 주변에 공백을 두므로 다른 경로를 만듭니다.헤더 파일의 포함은 분명히 실패할 것입니다.
결론
네, 클랑 포맷은 코드를 깨뜨릴 수 있습니다.에지 케이스이거나 언어 표준을 벗어나거나 단순히 특정 컴파일러(clang이 아닌) 확장자인 매우 특정 구문을 사용하는 경우에는 clang-format에 의해 변경된 내용을 확인해야 합니다.그렇지 않으면 숨겨진 오류가 발생할 위험이 있습니다.
, 도입니다온rclang-format
, 오늘 저는 이 문제에 직면했습니다.저의 사용 사례는 버그에 설명된 것과 유사했습니다.
int main() {
int x = 0;
int y = 0;
return x < y - 1 >> 1;
}
다음과 같이 다시 포맷할 수 있습니다.
int main() {
int x = 0;
int y = 0;
return x < y - 1 > > 1; /*<< Code is broken*/
}
다행히 수리가 되었고, 툴 업데이트가 도움이 되었습니다!
클랑의 정적 분석에 기반을 두고 있기 때문에 단순히 텍스트만으로 작동하는 바보 같은 소스 코드 포맷터(컴파일러 라이브러리를 사용할 수 있다는 것 중 하나)가 아니라 코드 자체의 구조에 대한 지식을 가지고 있기 때문에 그렇지 않을 것이라고 생각합니다.포맷터가 컴파일러 자체와 동일한 파서와 렉서를 사용한다는 점을 고려하면, 당신이 입력한 것과 동일하게 동작하는 코드를 뱉어내는 데 문제가 없을 만큼 충분히 안전하다고 생각합니다.
C++ 포맷의 소스 코드는 여기 http://clang.llvm.org/doxygen/Format_8cpp_source.html 에서 확인할 수 있습니다.
언급URL : https://stackoverflow.com/questions/37927553/can-clang-format-break-my-code
'source' 카테고리의 다른 글
창이 없는 응용프로그램 만들기 (0) | 2023.09.24 |
---|---|
쿼리가 오라클 10g을 중단합니다. (0) | 2023.09.24 |
html을 사용하여 Action에 파라미터를 전달하려면 어떻게 해야 합니까?ASP에서 액션().NET MVC? (0) | 2023.09.24 |
c: 공극 크기* (0) | 2023.09.24 |
Python 해시 가능한 명령어 (0) | 2023.09.19 |