Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Clang warning for uninitialized field in struct

Tags:

c

struct

clang

Consider the following struct:

typedef struct foo {
    int a;
    int b;
} foo;

My compiler issues no warning for the following statement:

foo m = {300}

Why is no warning emitted? I expected a warning, since I have not provided any value for the final field of the struct.

Here is my compiler invocation:

gcc -Wall -Wpadded -Wuninitialized -g bar.c

Here is my gcc version:

Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin15.0.0
Thread model: posix

Will the flipped_move field just contain garbage? Is this safe?

like image 300
dylhunn Avatar asked Jun 05 '16 01:06

dylhunn


2 Answers

-Wuninitialized warns about uninitialised variables. But your compound literal very well is completely initialised.

C does not support partial initialisation. Fields in structs and array initialisers or a compound literal which are not explicitly given are automatically set to 0/0.0/null pointer (depending on type). So there is no need for the compiler to warn.

Maybe it is better practice in modern C to use designated initialisers, instead of the positional ones:

(move){orig_c, curr_c, ... }

Will store values to the first, second, etc. field, no matter which names it has and its type. This will cause trouble if you e.g. remove a field, but forget to remove the value:

// from field removed
(move){orig_c, curr_c, ... }

will set to and the following field. While this will generate an error for your struct, imagine the types were compatible.

Designated initialisers don't have this problem:

(move){ .from = orig_c, .to = curr_c, ... }

If you remove from, you will get an error about an unknown field name if you forget to change that list, too. Also you easier will see if you forgot a field. This is especially helpful for larger structs.


Sidenote: Your compiler is not gcc, but llvm/clang. Apple unfortunately linked gcc to that compiler when they changed the toolchain for compatibility reasons. Bad idea, as the compilers are not fully compatible.

like image 115
too honest for this site Avatar answered Nov 03 '22 23:11

too honest for this site


-Wmissing-field-initializers will warn you about missing field initializers in your struct initialization.

However, it looks like on clang that flag won't warn you if you choose to initialize a struct with no values. For example

struct foo{
  int a;
};

int main(int argc, char **argv) {
  struct foo f = {};
  return 0;
}

Will emit no warnings even with -Wmissing-field-initializers on. If you'd like warnings in this case as well you should add the -Wgnu-empty-initializer.

GCC

Although you asked about clang, this also works in GCC
GCC will emit warnings for both cases when you pass in -Wmissing-field-initializers. There is no -Wgnu-empty-initializer flag for GCC.

like image 42
Jason Teplitz Avatar answered Nov 03 '22 23:11

Jason Teplitz