Any smart way how to get rid of "uninitialised" wa

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In a complex function, I get the "variable may be used uninitialised" warning. gcc manual in "3.8 Options to Request or Suppress Warnings", for this type of warning, says, "These warnings are made optional because GCC is not smart enough to see all the reasons why the code might be correct despite appearing to have an error." What I have is something similar to the example of that very section in manual:

          {
            int save_y;
            if (change_y) save_y = y, y = new_y;
            ...
            if (change_y) y = save_y;
          }

I can't reproduce it with anything simpler but the full blown version of my code (which will relate to the fact that this warning is related somehow to optimisation), but the principle is the same: first a flag gets set condition to external events, then a variable gets set if the flag is true; and much later in the same routine - with no change of the flag meantime - the variable is used under the same condition, i.e. if the flag is true.

I understand and am content with the limitations of the - undoubtedly complex - algorithm of evaluating this warning.

However, I want to get rid of this warning *selectively*, as I still want the compiler to warn me if I use an uninitialised variable elsewhere, it IS an useful feature. AFAIK gcc doesn't have an equivalent of the "local" "#pragma (no)warn xxx" known in many other C compilers. The easy way is to explicitly initialise the variable, but - we are talking small embedded here, don't we - I don't want to waste execution time/code memory just to make the compiler happy.

This is nothing critical, but I am curious if this can be circumvented somehow.

Any ideas?

Thanks,

Jan Waclawek

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I assume you've tried the obvious:

          {
            int save_y = 0;
            if (change_y) save_y = y, y = new_y;
            ...
            if (change_y) y = save_y;
          } 

No clue if this causes problems or not.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If save_y is never used anywhere else except for the initialization and clean-up of this function block, then how about something like this: (I hope you're forgive the fact that I modified your layout somewhat to match my parenthesis style.)

{
   int save_y = y;
   if(change_y)
   {
      y = new_y;
   }
   ...
   if(change_y)
   {
      y = save_y;
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm ...

I wasn't even aware that this comma separation of 2 statements was legal.

Quote:
if (change_y) save_y = y, y = new_y;

But what the compiler prob. is complaining about is that : if change_y is false in the first test , and becomes true in the 2'nd , then you have assigned y = save_y , and save_y was never initialized in the first block.

Do one of the above suggested things , and the warning will go away.

Btw: !!!!!!!

Disregarding/disabling the warnings GCC produces , is NOT a good idea.
They aren't there just to annoy you , but to help you.

/Bingo

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bingo600 wrote:
I wasn't even aware that this comma separation of 2 statements was legal.
Apparently, you are in need of the K&R C book or similar. Any good C book will discuss the comma operator, quite often used in the first and third parts of a "for" statement. See p. 62 of K&R (2nd edition).

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dkinzer wrote:
Bingo600 wrote:
I wasn't even aware that this comma separation of 2 statements was legal.
Apparently, you are in need of the K&R C book or similar. Any good C book will discuss the comma operator, quite often used in the first and third parts of a "for" statement. See p. 62 of K&R (2nd edition).

I have the K&R book(s) , and have even used the for(x=1,y=2;...;....)

But it didn't occur to me that you could use it that way.

Even though i have made more of these , than the for's :

int a=1,b=0,c=22;

Hmmm ... maybe time to dust off the K&R and glance through it again.

/Bingo

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks all for the suggestions.

Bingo600 wrote:
Hmm ...

I wasn't even aware that this comma separation of 2 statements was legal.


C was designed to compile the Manhattan phone directory cleanly, not that it's a good idea.

This was not my example, it's a quote from gcc manual. Now, manuals are here to teach some good stuff, they say... :-(

Bingo600 wrote:
But what the compiler prob. is complaining about is that : if change_y is false in the first test , and becomes true in the 2'nd , then you have assigned y = save_y , and save_y was never initialized in the first block.

In my code, change_y does not change between the two tests.

Bingo600 wrote:
Do one of the above suggested things , and the warning will go away.

Both result in unnecessary code. I said in my original post, I want to avoid that.

Bingo600 wrote:
Disregarding/disabling the warnings GCC produces , is NOT a good idea.
They aren't there just to annoy you , but to help you.

I know; the manual specifically says (see quote in my original post) that this warning may go astray. This is why do I want to disable it selectively, not globally by command-line switch.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

maybe declaring the variable as volatile helps?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
The easy way is to explicitly initialise the variable, but - we are talking small embedded here, don't we - I don't want to waste execution time/code memory just to make the compiler happy.
So, are you already on the edge in terms of size and/or speed? If yes, I can understand your desire to save every single bit of code or clock cycle. Otherwise I would just initialize the variable and maybe add a "fixme" or "sizeme" or "speedme" comment. And come back only when I absolutely have to.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
unnecessary code
Anytime I see 'int' being used for a variable (even in examples- 'int save_y'), it seems that may be the 'default' thinking for variables. You may need them that size, but if a uint8_t will do, that will be a bigger deal than a simple variable initialization. You may be saving 2 bytes/1 cycle by not initializing that variable (not a big gain), all the while you are working with ints when not needed (big loss).

Just a thought.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
So, are you already on the edge in terms of size and/or speed?

I see your point, thanks. No, I am not on the edge, and I already had the initialiser there (together with the comment :-) ) at the moment I wrote my initial post.

I tried to make clear in my initial post, that I am not after ANY solution, just SMART solutions... ;-)

curtvm wrote:
Anytime I see 'int' being used for a variable (even in examples- 'int save_y'), it seems that may be the 'default' thinking for variables.
That example was a quote from the gcc manual, so it was most probably intended for "big computers", where int, "the natural word width of a machine", is fully appropriate.

jayjay1974 wrote:
maybe declaring the variable as volatile helps?

I doubt it. It would prevent the optimiser to keep the variable in question in registers and use other optimisations, which again results generally in unnecessarily bigger and slower code. Volatile should thus be avoided except if explicitly needed.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree with the OP's wish to have a method at hand to selectively suppress such a warning about uninitialized variables. Just look at this example of a bit-reversing function:

uint16_t Reverse(uint16_t Val) {
uint8_t i;
uint16_t Res;
  for (i = 16; i>0; i--) {
    Res <<= 1;
    if (Val & 1)
      Res++;
    Val >>= 1;
  }
  return Res;
}

Here, the compiler complains about Res being uninitialized, which is absolutely correct. But, any initialization of Res is totally unnecessary, since it will be filled by left-shifts and increments bit for bit within the for loop.

To keep a compilation log clean of any warnings, of course the first step should always be to correct or adapt your code. But again, there will be valid situations/code constructs where forcing the compiler to "accept that the programmer has done his homework" would be the only way to get rid of warnings.

And yes, initializing Res to an initial value will again be the easiest way of getting rid of the warning, but this adds code, plus it gives me the feeling to have to obey the compiler, where i know i'm the one with more intelligence :-) , at least in that particular case...

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK here's an "off the wall" idea. First start by turning off all compiler warnings (I know, I know!). But then modify your makefiles so the compiler simply doesn't get invoked until the code has successfully been lint'd or splint'd without any warnings. Naturally lint is going to warn about this but the great thing about lint/splint is that you can temporarily suppress any form of warning using codes embedded in comments close to the offending code. So it offers the feature that C appears to be missing. ;-)

Cliff

PS The reason I suggest this is that we do something very like this in any of our lintable projects (some cannot be because they contain too much 3rd party input and we can never persuade them to adopt lint too)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff,

with your proposed ...hmmm... workaround, i'll prefer to stay with getting the warning ;-)

-- Thilo

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just init it to zero.

All varaible that are not inited should have the value zero. The compiler is clever enough to figure out that you have an "un-needed" init, and will remove the init. Thus, there is no extra use of flash.

Refer:
http://www.nongnu.org/avr-libc/u...

At least that's how I interpret it...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the compiler is indeed "clever enough to figure out that you have an un-needed init", then why in heaven would he spit out that warning in the beginning?

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Heisann wrote:
All varaible that are not inited should have the value zero.

This is only for global and static variables. Local non-static variables are uninitialised - and it's only these variables for which the warning can occur.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't know that, thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
Bingo600 wrote:
Do one of the above suggested things , and the warning will go away.

Both result in unnecessary code. I said in my original post, I want to avoid that.

I wouldn't expect the code I suggested to result in even a single word increase in the total size of code generated - all it does is move the variable assignment outside the if statement.

Granted, it would result in a couple extra instruction cycles' worth of delay that wouldn't have been necessary in situations where change_y was false.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Highly opinous, I know...

Hand-optimizing Rule #1: Don't.

Hand-optimizing Rule #2: Don't do it yet. If you really need to, don't do it until it is absolutely necessary (ie when some resource limit is actually reached).

Hand-optimizing Rule #3: When that time comes, analyse where an optimisation will do the most good and the least harm (all optimisations are harmful - they de-optimise the maintainability of the code). Do that optimisation. Repeat this rule until within limit(s) again, then immediately stop (do not do an un-necessary codesize/memconsumption/runtime optimisation that will sacrifice code quality/maintainability).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But, Johan, there is not a single world about optimisation here. What I want is to *avoid pessimisation* - namely, putting unnecessary initialisers or assignments, just to make the compiler happy.

lfmorrison, sure, your way is better than a dumb initialiser, but still a bow to the quirk of the compiler.

Btw, note, that there IS one similar local warning suppression implemented (albeit in a different form than the commonly used #pragma (no)warn mechanism): attribute unused.

OK, I know what's coming next: "this is open source software, feel free to implement your way for local warning suppression, and submit it as a patch" :-( .

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But, Johan, there is not a single world about optimisation here.

Uh, isn't that a play with words? Anyway, read my "hand optimization" as "fiddling with C source code so the compiler does not emit relativey small amounts of useless code, and similar". IMO avoiding the initialization of the variable is just that.

As I told you elsewhere, I am not against doing these hand optimisations as a game or learning experience. I do that all the time. It enhances my competence, and is great fun! But when it gets to production code I favour the principle of "optimise for maintenance before optimising for performance until performance is a show stopper". I've been programming for over 30 years, and I've been hit by my own bad or illegible code a lot more often than by performance issues.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:

But, Johan, there is not a single world about optimisation here.

Uh, isn't that a play with words?

No.

While "optimisation" is "remove unnecessary", "avoid pessimisation" is "don't put in unnecessary".

The developer, who is ready to put in the unnecessary initialisation/assignment, to suppress the warning, would be much happier with the possibility of local warning suppression.

Note, that authors of gcc are well aware of the defficiency of this particular warning detecting algorithm (manual says: "These warnings are made optional because GCC is not smart enough [...] "), but provided no other means of getting rid of them but globally disabling the warning (I still refuse to deem the unnecessary initialisation/assigment a real solution to the problem). There's a handful of bug report/enhancement request in gcc's tracker already, and an extensive treatment here.

But, it appears, the gcc developers are either unaware of an option to suppress the warning locally, upon discretion of the developer; or they systematically ignore this option for some reason. They, for some reason, focus desperately to attempts to perfect the warning algorithm, although, at the same time, they explicitly recognize, that

GCC wiki - I gave the link above - wrote:
Not matter what we do, we will never be able to get the correct answer for every possible program.

At the same time, as I have already said, a similar local warning suppression is already in place for the unused variables. I can't see what might be the difference preventing gcc developers to do the same for the "unused".

It might be nice to submit a enhancement request to gcc's bug tracker, but I am not going to go through the required registration etc., for this.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 static int save_y; 

Would probably work,
I don't know if it increases code size but it does increase your RAM usage.

Paul.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
I don't know if it increases code size but it does increase your RAM usage.
This tactic also makes the routine not reentrant.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net