Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #163727 > unrolled thread

on ``warning: array subscript has type ‘char’''

Started byMeredith Montgomery <mmontgomery@levado.to>
First post2021-12-06 17:40 -0300
Last post2021-12-07 15:11 -0300
Articles 3 — 2 participants

Back to article view | Back to comp.lang.c


Contents

  on ``warning: array subscript has type ‘char’'' Meredith Montgomery <mmontgomery@levado.to> - 2021-12-06 17:40 -0300
    Re: on ``warning: array subscript has type ‘char’'' Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-12-06 13:12 -0800
      Re: on ``warning: array subscript has type ‘char’'' Meredith Montgomery <mmontgomery@levado.to> - 2021-12-07 15:11 -0300

#163727 — on ``warning: array subscript has type ‘char’''

FromMeredith Montgomery <mmontgomery@levado.to>
Date2021-12-06 17:40 -0300
Subjecton ``warning: array subscript has type ‘char’''
Message-ID<86mtldsbzf.fsf@levado.to>
I can't explain this.

%make warning
gcc -Wall -x c -g -std=c99 -pedantic-errors    warning.c   -o warning
In file included from warning.c:2:
warning.c: In function ‘getop’:
warning.c:38:27: warning: array subscript has type ‘char’ [-Wchar-subscripts]
   38 |     while (isdigit(s[++i] = c = getch()))
      |                    ~~~~~~~^~~~~~~~~~~~~

I understand the warning is trying to tell me that a char is not a good
idea as an array subscript as a char could be negative.  However, the
array subscript is /i/, not /c/.  So I'm puzzled.  Thank you!

This is essentially the reverse-polish calculator by Brian Kernighan in
chapter 4 of K&R.  The relevant code is the following.  (See full source
of the program warning.c below.)

int getch(void) { /* get a (possibly pushed-back) character */
  if (p > 0) 
    return buf[--p];
  else 
    return getchar();
}

int getop(char s[]) {
  int i, c;

  while ((s[0] = c = getch()) == ' ' || c == '\t')
    ; /* skip white space */

  s[1] = '\0'; 

  if (!isdigit(c)) {
    return c; /* not a digit, not an integer */
  }

  i = 0;
  if (isdigit(c)) /* read the integer into s until its end */
    while (isdigit(s[++i] = c = getch()))
      ;
  s[i] = '\0'; /* close the string */

  if (c != EOF)
    ungetch(c); 

  return NUMBER;
}

--8<---------------cut here---------------start------------->8---
--8<---------------cut here---------------end--------------->8---

(*) Full source code

#include <stdio.h>
#include <ctype.h>

#define NUMBER '\0'

#define BUFSIZE 100
char buf[BUFSIZE]; /* a buffer for ungetch() */
int p = 0; /* the next free position in buf */

int getch(void) { /* get a (possibly pushed-back) character */
  if (p > 0) 
    return buf[--p];
  else 
    return getchar();
}

void ungetch(int c) {
  if (p >= BUFSIZE)
    printf("ungetch: too many characters; buffer full\n");
  else
    buf[p++] = c;
}

int getop(char s[]) {
  int i, c;

  while ((s[0] = c = getch()) == ' ' || c == '\t')
    ; /* skip white space */

  s[1] = '\0'; 

  if (!isdigit(c)) {
    return c; /* not a digit, not an integer */
  }

  i = 0;
  if (isdigit(c)) /* read the integer into s until its end */
    while (isdigit(s[++i] = c = getch()))
      ;
  s[i] = '\0'; /* close the string */

  if (c != EOF)
    ungetch(c); 

  return NUMBER;
}

int main(void) {
  char buf[100]; int i;
  ungetch('1');
  i = getop(buf); printf("i = %d, buf = %s\n", i, buf);

  return 0;
}

[toc] | [next] | [standalone]


#163728

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-12-06 13:12 -0800
Message-ID<87v901bfp3.fsf@nosuchdomain.example.com>
In reply to#163727
Meredith Montgomery <mmontgomery@levado.to> writes:
> I can't explain this.
>
> %make warning
> gcc -Wall -x c -g -std=c99 -pedantic-errors    warning.c   -o warning
> In file included from warning.c:2:
> warning.c: In function ‘getop’:
> warning.c:38:27: warning: array subscript has type ‘char’ [-Wchar-subscripts]
>    38 |     while (isdigit(s[++i] = c = getch()))
>       |                    ~~~~~~~^~~~~~~~~~~~~
>
> I understand the warning is trying to tell me that a char is not a good
> idea as an array subscript as a char could be negative.  However, the
> array subscript is /i/, not /c/.  So I'm puzzled.  Thank you!
[...]

The isdigit() function is probably implemented as a macro that uses
array indexing.  (All library functions can also be implemented as
macros.)  The part of the compiler that generates the warning message
doesn't know that the array indexing operator is the result of a macro
expansion, so it warns you as if you had written the indexing operator
directly.

If you replace `isdigit` by `(isdigit)` or precede the call by
    #undef isdigit
it will bypass the macro and call the actual function, and you probably
won't see the warning.  I suggest this as a diagnostic method, not as a
solution.

Having said that, the warning is quite useful even if it's less than
clear.  The argument to isdigit() is of type int, and is required to be
either within the range of unsigned char *or* equal to EOF (which is
typically -1).  Which means, annoyingly, that a char value passed to
isdigit() and friends should be cast to unsigned char.  Passing a
negative char value (other than EOF) to isdigit() has undefined behavior.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#163731

FromMeredith Montgomery <mmontgomery@levado.to>
Date2021-12-07 15:11 -0300
Message-ID<86czm8s2sx.fsf@levado.to>
In reply to#163728
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Meredith Montgomery <mmontgomery@levado.to> writes:
>> I can't explain this.
>>
>> %make warning
>> gcc -Wall -x c -g -std=c99 -pedantic-errors    warning.c   -o warning
>> In file included from warning.c:2:
>> warning.c: In function ‘getop’:
>> warning.c:38:27: warning: array subscript has type ‘char’ [-Wchar-subscripts]
>>    38 |     while (isdigit(s[++i] = c = getch()))
>>       |                    ~~~~~~~^~~~~~~~~~~~~
>>
>> I understand the warning is trying to tell me that a char is not a good
>> idea as an array subscript as a char could be negative.  However, the
>> array subscript is /i/, not /c/.  So I'm puzzled.  Thank you!
> [...]
>
> The isdigit() function is probably implemented as a macro that uses
> array indexing.  (All library functions can also be implemented as
> macros.)  The part of the compiler that generates the warning message
> doesn't know that the array indexing operator is the result of a macro
> expansion, so it warns you as if you had written the indexing operator
> directly.
>
> If you replace `isdigit` by `(isdigit)` or precede the call by
>     #undef isdigit
> it will bypass the macro and call the actual function, and you probably
> won't see the warning.  I suggest this as a diagnostic method, not as a
> solution.
>
> Having said that, the warning is quite useful even if it's less than
> clear.  The argument to isdigit() is of type int, and is required to be
> either within the range of unsigned char *or* equal to EOF (which is
> typically -1).  Which means, annoyingly, that a char value passed to
> isdigit() and friends should be cast to unsigned char.  Passing a
> negative char value (other than EOF) to isdigit() has undefined behavior.

Lol!  That's the C language we love!  Order is back in the house now.
Thank you so much for the great info.  It did not occur to me that
/isdigit/ could be macro.  I will probably never forget this anymore.
Thank you!

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web