C 叮当格式能破坏我的代码吗?
由于C 叮当格式能破坏我的代码吗?,c,clang-format,C,Clang Format,由于clangformat是一种仅用于重新格式化代码的工具,这种格式化是否可能会破坏工作代码,或者至少会改变其工作方式?是否存在某种合同,它将/不能改变代码的工作方式 我们有很多代码需要使用clangformat进行格式化。这意味着,许多代码行将发生更改。不必检查每一行只因铿锵格式而更改的代码,这将大大简化此过程 我想说,clangformat不会改变代码的工作方式。另一方面,如果这可以保证,我不能100%肯定。我想它不会,因为它是建立在clang的静态分析基础上的,因此了解代码本身的结构,而不
clangformat
是一种仅用于重新格式化代码的工具,这种格式化是否可能会破坏工作代码,或者至少会改变其工作方式?是否存在某种合同,它将/不能改变代码的工作方式
我们有很多代码需要使用clangformat
进行格式化。这意味着,许多代码行将发生更改。不必检查每一行只因铿锵格式而更改的代码,这将大大简化此过程
我想说,clangformat
不会改变代码的工作方式。另一方面,如果这可以保证,我不能100%肯定。我想它不会,因为它是建立在clang的静态分析基础上的,因此了解代码本身的结构,而不仅仅是一个只对文本进行操作的愚蠢的源代码格式化程序(能够使用编译器库的好处之一)。假设格式化程序使用与编译器本身相同的解析器和lexer,我会感到足够安全,这样它就不会出现任何问题,即吐出与您提供给它的行为相同的代码
这里可以看到C++格式化程序的源代码:
< p>因为 CLAN格式只影响空白字符,您可以检查代码之前和之后的代码> CLAN格式< /代码> ING与空白相同。在Linux/BSD/OS X中,您可以使用diff
和tr
来实现:
$ diff --ignore-all-space <(tr '\n' ' ' < 2.c ) <(tr '\n' ' ' < 1.c)
$diff——忽略所有空格,确保它可以更改代码的工作方式。原因是C程序可以查看其源代码的某些属性。我想的是\uuuu LINE\uuuu
宏,但我不确定是否还有其他方法
考虑1.c
:
#include <stdio.h>
int main(){printf("%d\n", __LINE__);}
In file included from restyled.c:1:
./MyStruct.h:2:5: error: unknown type name 'uint8_t'
uint8_t value;
^
1 error generated.
现在执行一些clangformat
:
> clang-format -style=Chromium 1.c >2.c
而2.c
是:
#include <stdio.h>
int main() {
printf("%d\n", __LINE__);
}
简短回答:是的。
clangformat
工具有一个-sort includes
选项。更改#include
指令的顺序肯定会改变现有代码的行为,可能会破坏现有代码。
由于一些内置样式将相应的SortIncludes
选项设置为true
,因此clangformat
是否会对您的包含重新排序可能并不明显
MyStruct.h:
struct MyStruct {
uint8_t value;
};
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include "MyStruct.h"
#include <stddef.h>
#include <stdint.h>
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include <stddef.h>
#include <stdint.h>
#include "MyStruct.h"
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#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:
struct MyStruct {
uint8_t value;
};
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include "MyStruct.h"
#include <stddef.h>
#include <stdint.h>
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include <stddef.h>
#include <stdint.h>
#include "MyStruct.h"
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#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;
}
由于头文件的重新排序,我在编译restyled.c
时遇到以下错误:
#include <stdio.h>
int main(){printf("%d\n", __LINE__);}
In file included from restyled.c:1:
./MyStruct.h:2:5: error: unknown type name 'uint8_t'
uint8_t value;
^
1 error generated.
然而,这个问题应该很容易解决。不太可能有这样的顺序相关包含,但是如果有,可以通过在需要特定顺序的标题组之间放置一个空行来解决问题,因为显然clangformat
只对#include
指令组进行排序,中间没有非#include
行
固定原件。c:
struct MyStruct {
uint8_t value;
};
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include "MyStruct.h"
#include <stddef.h>
#include <stdint.h>
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
#include <stddef.h>
#include <stdint.h>
#include "MyStruct.h"
int main(int argc, char **argv) {
struct MyStruct s = {0};
return s.value;
}
#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;
}
clang format在项目中重新格式化了ASM代码,因为我们有效地做到了这一点:
#define ASM _asm
ASM {
...
}
是
它不会中断工作流程
系统具有配置开关:
“C_Cpp.clangg_格式”包括:false,
但它不起作用,我不知道怎么了
我的版本是:ms vscode.cpptools-0.13.1
这是我的解决方案:
对于稳定的工作流程,请使用语法:
//叮当作响
…这是你的密码
//除其他答案中描述的场景外,-sort includes
可能会中断使用预编译头的项目。如图所示:
一旦看到第一个C标记,就不能使用预编译头
这同样适用于VisualStudio
实际上,这通常意味着预编译头文件必须是第一个包含的头文件。如果让clangformat
为您排序,那么当预编译头不是第一个包含的文件时,您的编译很可能会中断
你可以将你的PCH文件命名为0000000000000000\u PCH.h
,但我想我已经用这样一个荒谬的例子表明了我的观点,如果clang格式破坏了有效的代码,那将是非常无用的,你不认为吗?@EOF,同意,但你能保证clang格式没有bug吗?:)可执行文件是否相同?此外,我认为@WeatherVane的问题是关键。如果编译原始程序和重新格式化的程序,并且生成的可执行文件相同,那么您可以确信没有语义更改。虽然我个人觉得你不太可能在叮当声格式中找到这种性质的bug,但如果你在一个需要极度偏执的环境中工作,那么测试将非常简单。如果你的项目是一个只包含头文件的库,或者也包含头文件,那么检查二进制文件是不够的,您还需要良好的覆盖率测试。。。这就是为什么我们在不同级别测试我们的软件;)好主意,不过从技术上讲,你仍然需要检查重要的空格(字符串)。另一个重要的空格是终止预处理器指令的换行符。还有分隔字母数字标记的空格-否则如果
不是elseif
,我们假设它不会破坏这些标记。在这两种情况下,你都应该期待语法错误,而不是语义上的细微变化。@KarolyHorvath:虽然我对clang格式不熟悉,但它的作者肯定想到了字符串文字?还有#define foo(bar)
和#define foo(bar)的区别
以及许多其他问题,如插入或删除新行时的更改。我认为“仅影响空白”并不完全正确,因为它会打断长字符串,引入额外的引号clang-format-5
还可以在名称空间结束大括号处引入注释,即}//namespa