简体   繁体   中英

Clang-Tidy: Initializing non-local variable with non-const expression depending on uninitialized non-local variable, C pointer reference

We have a very simple bit of code which is giving a warning but seems like it should be fine, and runs fine. We understand that in general there may be issues with order of initialisation between compilation units, but in this case we are initialising with a pointer, so don't understand how order can cause a problem, or how any problems might arise with this code. Note that in the real code we have more complex scenario with structs, but code below shows the basic issue.

EDIT: have removed const qualifiers as they don't affect the warning

file1.c

int foo=42;

file2.c

#include <stdio.h>

extern int foo;
// Clang-Tidy: Initializing non-local variable with non-const expression depending on uninitialized non-local variable 'foo'
int *bar=&foo;

int main() {
  printf("%d\n", *bar); // prints '42'
}

Warning is not from gcc but from clang-tidy . To reproduce run:

clang-tidy -checks=* file1.c file2.c

clang-tidy is warning about something that just is not a problem: whether foo is initialized or not does not make a difference in this initializer where only its address is taken.

Furthermore foo is a global variable, hence it is either statically initialized in the module that defines it or it does not have an initializer and is initialized to 0 by the loader at run time. If the program was compiled as C++, foo might be initialized at runtime, before main is called, potentially by running initializer code, but again this does not make a difference as only its address is used in int *bar = &foo;

You should just disable this warning, as explained by Cameron Tacklind .

As others have mentioned, clang-tidy is telling you precisely what is wrong.

In this case, I think the clincher is the first part of the sentence: "Initializing non-local variable ...".

The particular warning will go away if bar is declared (and defined) inside main() :

#include <stdio.h>

extern int foo;

int main() {
  int *bar=&foo; // Still warns about const issues

  printf("%d\n", *bar);
}

Alternatively, you can ignore the specific rule for those specific lines pretty easily:

#include <stdio.h>

extern int foo;

// NOLINTNEXTLINE(cppcoreguidelines-interfaces-global-init)
int *bar=&foo;

int main() {
  printf("%d\n", *bar);
}

In Ubuntu 20.04, I create such file1.c and file2.c, use gcc to compile them and run, but I didn't get any warning like you mentioned above, it works just fine.

In addition, in logical, I don't think it will cause any problem.

In C, keyword const means constant variable , which can not be changed. In your case, foo is a constant variable, its address is constant as well; you assign its address to another constant pointer variable bar , so bar is always pointing to foo , and both of them are constant variable, which means anytime *bar is equal to foo and vice versa.

By the way, maybe you were in rush when post your question, but I still recommend you to add a ; in the end of const int *bar=&foo , which resides in file2.c .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM