avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-chat] no compiler warnings from printf_P?


From: Britton Kerin
Subject: Re: [avr-chat] no compiler warnings from printf_P?
Date: Thu, 19 Mar 2015 13:27:48 -0800

On Tue, Mar 17, 2015 at 2:50 PM, Martin Stejskal <address@hidden> wrote:
> Hi,
> I think there is good reason, why AVR in default work with int instead of
> unsigned long (RAM bit wide). If you do not like this warning, just
> explicitly retype this constant.

Its not problem that int is a 16 bit type, that's meets standard int
width requirement
and is not unexpected on AVR.

> Reason, why warning is not in second case, is fact, that flash is 16bit
> wide,  so it is good reason to use 16 bit values, right? It made
> implementation easier.

I don't know.  The argument itself isn't (necesarilly) in flash, only the
string.  You don't expect that it would be treated differently.  How does
it make the implementation easier?

It seems pretty unfortunate that that second version prints a wrong value
without warning, especially in a case where programmers may have become
accustomed to having the compiler catch the error, and when it does in fact
catch it for ordinary printf.

I eventually found that there is a vfprintf_P (so why is there not a
vprintf_P?), so I was able to implement a safer version of printf_P()
like this:

  // In the header:
  int
  printf_P_safer (char const *fmt, ...) __attribute__ ((format (printf, 1, 2)));


  // In the corresponding .c:
  int
  printf_P_safer (char const *fmt, ...)
  {
    va_list ap;
    va_start (ap, fmt);
    int char_count = vfprintf_P (stdout, fmt, ap);
    va_end (ap);

    return char_count;
  }

The next mystery for me is that this line doesn't trigger the warning:

  printf_P_safer ( PSTR ("biggy: %lu\n"), 42);

But this line does:

  printf_P_safer ( ((const PROGMEM char *) "biggy: %lu\n"), 42);

According to 
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#ga75acaba9e781937468d0911423bc0c35
they should be equivalent, but looking in avr/pgmspace.h we find the
truth:

  #if defined(__DOXYGEN__)
  /*
   * The #define below is just a dummy that serves documentation
   * purposes only.
   */
  /** \ingroup avr_pgmspace
      \def PSTR(s)

      Used to declare a static pointer to a string in program space. */
  # define PSTR(s) ((const PROGMEM char *)(s))
  #else  /* !DOXYGEN */
  /* The real thing. */
  # define PSTR(s) (__extension__({static const char __c[] PROGMEM =
(s); &__c[0];}))
  #endif /* DOXYGEN */

So doxygen is lying to us about how things actually work, always a bad
idea IMO.

It's all really unfortunate because printf() on AVR is almost certain to be
used mainly for debugging and bugs in the debugging code send people on big
wild goose chases.

I'd love to help fix this if it's possible.

Britton



reply via email to

[Prev in Thread] Current Thread [Next in Thread]