Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #163727 > unrolled thread
| Started by | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| First post | 2021-12-06 17:40 -0300 |
| Last post | 2021-12-07 15:11 -0300 |
| Articles | 3 — 2 participants |
Back to article view | Back to comp.lang.c
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
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-12-06 17:40 -0300 |
| Subject | on ``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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Meredith Montgomery <mmontgomery@levado.to> |
|---|---|
| Date | 2021-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