0

I have the following code:

#include <ctype.h>

void myfn(void)
{
    uint8_t any0 = 'c';
    char any1 = 'c';

    if (isprint(any0))
    {
        return;
    }
    if (isprint(any1))
    {
        return;
    }
}

When I compile it with gcc for arm, I get the following error:

error: array subscript has type 'char' [-Werror=char-subscripts]
     if (isprint(any1))
     ^

If I pass an unit8_t to isprint, the compiler is happy, but not if I pass it a char.

The prototype for isprint is:

int isprint(int c);

It expects an int as parameter, I give it a char. I would expect it to complain about the type of the parameter, but not something unrelated as 'array subscript'.

The error goes away if I change the call to:

if (isprint((uint8_t)any1))

Is there something I have overlooked?

The compiler I use is:

GNU C (15:4.9.3+svn231177-1) version 4.9.3 20150529 (prerelease) (arm-none-eabi)
compiled by GNU C version 5.2.1 20151129, GMP version 6.1.0, MPFR version 3.1.3, MPC version 1.0.3
warning: MPFR header version 3.1.3 differs from library version 3.1.4.

Commandline options:

'-v' '-fshort-enums' '-specs=nosys.specs' '-specs=nano.specs'
'-mfloat-abi=soft' '-save-temps' '-Werror' '-Wpedantic' '-pedantic-errors' '-mthumb' '-fno-builtin' '-mcpu=cortex-m0' '-Wall' '-std=gnu99' '-ffunction-sections'
'-fdata-sections' '-fomit-frame-pointer' '-mabi=aapcs' '-fno-unroll-loops' '-ffast-math' '-ftree-vectorize' '-Og' '-g'

If I compile the same code with the gcc compiler for AVR /usr/bin/avr-gcc (using similar commandline options and I intentionally added option -Werror=char-subscripts), it doesn't complain about isprint. So it seems to be something related to the ARM compiler.

NZD
  • 1,780
  • 2
  • 20
  • 29
  • Probably a version difference, not specific to ARM or AVR. What version is your avr-gcc? Anyway, it's just a nanny warning. Your code is fine. Relevant: https://stackoverflow.com/questions/9972359/warning-array-subscript-has-type-char The reason you get an `array subscript` error rather than something about a function call parameter is likely that `isprint` is a macro in your implementation. – Carl Norum Sep 03 '19 at 23:51
  • @CarlNorum Yes, you are right. The implementation of `isprint` is a macro and, more importantly, header file ctype.h contains the following comment: `These macros are intentionally written in a manner that will trigger a gcc -Wall warning if the user mistakenly passes a 'char' instead of an int containing an 'unsigned char'.` – NZD Sep 04 '19 at 00:47
  • @CarlNorum My avr compiler is version 4.9.2 and header file ctype.h contains: `extern int isprint(int __c) __ATTR_CONST__;`. This explains the difference between AVR and ARM. – NZD Sep 04 '19 at 00:53

1 Answers1

0

It turned out that the implementation of isprint for ARM is a macro and, more importantly, header file ctype.h contains the following comment:

These macros are intentionally written in a manner that will trigger
a gcc -Wall warning if the user mistakenly passes a 'char' instead of
an int containing an 'unsigned char'.

For AVR, header file ctype.h contains:

extern int isprint(int __c) __ATTR_CONST__;

This explains the difference in behaviour when compiling for AVR or for ARM.

NZD
  • 1,780
  • 2
  • 20
  • 29