Re: getchar returns int, assign to array of char?

B

Ben Fitzgerald

In said:
it works fine, of course, but I just got lint recently
(actually splint on linux) and it complains:

Assignment of int to char: x[i++] = c
No, it is not the correct and portable approach, but for another reason
than the lint complaint.

You're assigning a value in the range 0..UCHAR_MAX to a variable that can
only represent the CHAR_MIN..CHAR_MAX range. Although this happens to
work most of the time on most of the platforms, it is not guaranteed by
the language to do the right thing.

One idea would be declare x as array of unsigned char. But, if you want
to pass it to a library expecting a string, you have a problem, because
it expects a pointer to char as argument. So, the right solution is to
use a pointer to unsigned char when storing values into your array:

int c, i = 0;
char x[20];
unsigned char *p = (unsigned char *)x;

while((c = getchar()) != EOF && i < sizeof x - 1)
p[i++] = c;

Okay, help me out here. If I assign c straight to x[i++]:
x[i++] = c;

I'm incorrect because c could contain a vaule greater than
UCHAR_MAX, but x can only hold CHAR_MIN...CHAR_MAX

*But*, if you have (c = getchar()) != EOF) as a test in your
while loop and getchar() "returns an unsigned char cast
to an int, or EOF" (I got this quote from a linux man page!)
then EOF cannot be assigned inside the loop thanks to the test
so the former (unsigned char) will be assigned to x[i++]

i.e.
int c, i = 0;
unsigned char x[20];

while ((c=getchar()) != EOF && i < sizeof x - 1)
x[i++] = c;

Therefore, shouldn't array x simply be of type unsigned char!?
I am agreeing with you in a roundabout way, just without the
pointers, I think.

What do you reckon?
 
M

Micah Cowan

Ben Fitzgerald said:
In said:
it works fine, of course, but I just got lint recently
(actually splint on linux) and it complains:

Assignment of int to char: x[i++] = c
No, it is not the correct and portable approach, but for another reason
than the lint complaint.

You're assigning a value in the range 0..UCHAR_MAX to a variable that can
only represent the CHAR_MIN..CHAR_MAX range. Although this happens to
work most of the time on most of the platforms, it is not guaranteed by
the language to do the right thing.

One idea would be declare x as array of unsigned char. But, if you want
to pass it to a library expecting a string, you have a problem, because
it expects a pointer to char as argument. So, the right solution is to
use a pointer to unsigned char when storing values into your array:

int c, i = 0;
char x[20];
unsigned char *p = (unsigned char *)x;

while((c = getchar()) != EOF && i < sizeof x - 1)
p[i++] = c;

Okay, help me out here. If I assign c straight to x[i++]:
x[i++] = c;

I'm incorrect because c could contain a vaule greater than
UCHAR_MAX, but x can only hold CHAR_MIN...CHAR_MAX

No, c will either hold a value from 0 to UCHAR_MAX (not greater), or
it will hold the value EOF.
*But*, if you have (c = getchar()) != EOF) as a test in your
while loop and getchar() "returns an unsigned char cast
to an int, or EOF" (I got this quote from a linux man page!)
then EOF cannot be assigned inside the loop thanks to the test
so the former (unsigned char) will be assigned to x[i++]

Right, but that's the problem: assigning an unsigned char to a char
can overflow when char is a signed type.

If you are expecting that your file is made up entirely of textual
characters which are all representable in the char type, then you can
perform a check such as:

if (c > CHAR_MAX) {
/* c can't be represented as a regular char.
handle this as an error... */
}

Otherwise, if you want these bytes to be represented exactly, you
should follow Dan's advice.
i.e.
int c, i = 0;
unsigned char x[20];

while ((c=getchar()) != EOF && i < sizeof x - 1)
x[i++] = c;

Therefore, shouldn't array x simply be of type unsigned char!?
I am agreeing with you in a roundabout way, just without the
pointers, I think.

But, as Dan pointed out, you would then have difficulties using x with
the Standard Library's string manipulation facilities.

-Micah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top