0

I'm getting a warning ([-Wmaybe-uninitialized]) on some code that I don't think should be throwing a warning. Compiling with cmake using GCC. Basically it's saying that a variable may not be initialized, but I think it's guaranteed to be initialized. Here's an example:

#include<iostream>

enum class ByteOrder
{
    little_endian,
    big_endian
};

class someClass
{
    someClass(ByteOrder order = ByteOrder::little_endian) :
              kOrder{order}
    {}

    void someFunc();

private:
    const ByteOrder kOrder;
};

void someClass::someFunc()
{
    int i;

    switch(kOrder)
    {
        case ByteOrder::little_endian:
            i = 0;
            break;
        case ByteOrder::big_endian:
            i = 1;
            break;
    }

    std::cout << i;
}

According to GCC, i at the line

std::cout << i;

could be uninitialized. But I don't see how that's possible since there are only two options in the switch statement. I tried setting ByteOrder to nullptr but that didn't work. Am I missing something here?

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • 5
    The compiler doesn't assume that `kOrder` will always be one of the two values. Strictly speaking, someone could assign a value to `kOrder` that isn't one of the `enum` values. For example `someClass myThing{static_cast(42)};` – François Andrieux Jan 24 '22 at 22:22
  • 1
    The error is correct. To solve it, decide where you want to place `default:` in your switch statement. Or replace the whole switch with `int i = static_cast(kOrder);` – Drew Dormann Jan 24 '22 at 22:26
  • 1
    Please only post code verbatim that you have actually checked to produce the error/warning. For this time, I have fixed a few obvious mistakes that made it impossible to compile the code, but which I think are not relevant to your actual question. – user17732522 Jan 24 '22 at 22:39
  • Worse, by making changes to code to correct deficiencies and produce a working example, a potential answerer could accidentally insert an new mistake and make useless answers based on the new mistake or accidentally correct the mistake and provide no answer. – user4581301 Jan 24 '22 at 22:55
  • Latest [gcc and clang are fine with this code](https://godbolt.org/z/qe57GKjnK), msvc complains. – Marek R Jan 24 '22 at 23:31
  • Related SO question: https://stackoverflow.com/a/18195408/1387438 (not a duplicate). – Marek R Jan 24 '22 at 23:35
  • 1
    You know, there's an enum class `std::endian` in the standard library. No need to define another yourself (if you're using C++20 or later). – eerorika Jan 24 '22 at 23:39

2 Answers2

4

To illustrate the comments to your question, try this:

const ByteOrder kOrder = (ByteOrder)3;

Bottom line: just add the default: case, you may want to throw from there.

Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
0

Everyone had great input on this. I ended up solving this by just initializing my variable to an arbitrary value. We didn't want to use default because we wanted to keep the warnings that show up when you don't have an exhaustive switch statement for an enum. Thanks to everyone for answering.

  • Wouldn't it be easier to do `bool is_big_endian`? Then you are limited to only two cases: `true` or `false`. May not even need a `switch` :) – Vlad Feinstein Jan 25 '22 at 21:03