clang格式可以破坏我的代码吗?

时间:2016-06-20 16:32:53

标签: c clang-format

由于clang-format是一个只重新格式化代码的工具,这种格式化是否有可能破坏工作代码或至少改变它的工作方式?是否存在某种合同,它将/不能改变代码的工作方式?

我们要使用clang-format格式化大量代码。这意味着,许多代码行都会改变。不必审查由于clang-format而仅更改的每一行代码,都将大大简化此过程。

我会说clang-format不会改变代码的工作方式。另一方面,如果可以保证,我不是百分百肯定。

6 个答案:

答案 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.hstddef.h仍然重新排序,因为它们的包含仍然是&#34;分组&#34;,但是新的空行阻止了MyStruct.h在{标准库包括。

然而...

如果重新排序#include指令会破坏您的代码,您可能应该执行以下操作之一:

  1. 明确包含头文件中每个标头的依赖项。在我的示例中,我需要在stdint.h中加入MyStruct.h

  2. 在明确说明排序依赖关系的包含组之间添加注释行。请记住,任何非#include行都应该分组,因此注释行也可以使用。以下代码中的注释行也会阻止clang-format在标准库标题之前包含MyStruct.h

  3. <强>交替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>"; } ?> 与空格相同。

正如他在评论中提到的enter image description here,请注意在理想条件下,您仍然需要检查重要的空格,例如字符串文字。但在现实世界中,我相信这个测试已经足够了。

答案 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