由于clang-format
是一个只重新格式化代码的工具,这种格式化是否有可能破坏工作代码或至少改变它的工作方式?是否存在某种合同,它将/不能改变代码的工作方式?
我们要使用clang-format
格式化大量代码。这意味着,许多代码行都会改变。不必审查由于clang-format
而仅更改的每一行代码,都将大大简化此过程。
我会说clang-format
不会改变代码的工作方式。另一方面,如果可以保证,我不是百分百肯定。
答案 0 :(得分:50)
clang-format
工具有-sort-includes
选项。更改#include
指令的顺序肯定会改变现有代码的行为, 可能会破坏现有代码。
由于几个内置样式将相应的SortIncludes
选项设置为true
,因此clang-format
可能不会明显重新排序您的包含。
<强> MyStruct.h:强>
struct MyStruct {
uint8_t value;
};
<强> original.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
行。
<强>固定original.c:强>
#include <stdint.h>
#include <stddef.h>
#include "MyStruct.h"
int main (int argc, char **argv) {
struct MyStruct s = { 0 };
return s.value;
}
<强>固定restyled.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
仍然重新排序,因为它们的包含仍然是&#34;分组&#34;,但是新的空行阻止了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;
}
答案 1 :(得分:7)
当然,它可以改变代码的工作方式。原因是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
答案 2 :(得分:4)
由于clang-format
仅影响空格字符,因此您可以检查diff
之前和之后的文件是否与空格相同。在Linux / BSD / OS X中,您可以使用tr
和$ diff --ignore-all-space <(tr '\n' ' ' < 2.c ) <(tr '\n' ' ' < 1.c)
:
#include <stdio.h>
int main() {printf("Hello, world!\n"); return 0;}
1.C:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
2.C:
diff
1.c
命令的输出为空,表示文件2.c
和<form name="train" method="GET" action="test.php">
<select name="object">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="all">Show All</option>
</select>
<input type="submit" name="submit" id="submit" value="submit" size="10">
</form>
<?php
$train[0] = "pencil";
$train[1] = "macaron";
$train[2] = "notes";
$train[3] = "book";
$train[4] = "eraser";
$train[5] = "cake";
$train[6] = "laptop";
$train[7] = "mint";
$train[8] = "cup";
if ($_GET['submit']) {
$train = $_GET['obejct'];
echo "<p>I have $train!</p>";
}
?>
与空格相同。
正如他在评论中提到的,请注意在理想条件下,您仍然需要检查重要的空格,例如字符串文字。但在现实世界中,我相信这个测试已经足够了。
答案 3 :(得分:2)
是强>
不会破坏工作流程
系统有配置开关: “C_Cpp.clang_format_sortIncludes”:false , 但它不起作用,我不知道出了什么问题......
我的版本是:ms-vscode.cpptools-0.13.1
这是我的解决方案:
对于稳定的工作流程,请使用语法:
// clang-format off
...这是您的代码
// clang-format on
答案 4 :(得分:1)
clang-format重新格式化项目中的ASM代码,因为我们有效地做到了这一点:
#define ASM _asm
ASM {
...
}
答案 5 :(得分:-4)
我认为它不会,因为它是基于clang的静态分析,因此知道代码本身的结构,而不仅仅是一个单独操作文本的哑源代码格式化程序(一个能够使用编译器库的恩惠)。鉴于格式化程序使用与编译器本身相同的解析器和词法分析器,我感到足够安全,以至于没有任何问题会吐出与您提供的代码行为相同的代码。
您可以在此处查看C ++格式化程序的源代码:http://clang.llvm.org/doxygen/Format_8cpp_source.html