473,785 Members | 2,466 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Char difference between C90 and C99

Dear C people,

C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?

Thanks,
Jason.
Nov 14 '05 #1
11 2974
Jason Curl <j_********@mot orola.com> writes:
C90 doesn't specify if 'char' is either 'signed char' or 'unsigned
char' leaving it to the implementation of the compiler. Has this
changed for C99, or is it still the same?


Still the same.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #2
On Tue, 21 Jun 2005 08:57:10 +0200, Jason Curl wrote:
Dear C people,

C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
It says that char has the same range, representation and behaviour as
either signed char or unsigned char. However it is still a distinct type
from both. That means for example

char *p1 = NULL;
signed char *p2 = p1;

is invalid even on implementations where char has a signed representation.
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?


Yes, it is the same.

Lawrence
Nov 14 '05 #3

"Lawrence Kirby" <lk****@netacti ve.co.uk> wrote in message
news:pa******** *************** *****@netactive .co.uk...
On Tue, 21 Jun 2005 08:57:10 +0200, Jason Curl wrote:
Dear C people,

C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'


It says that char has the same range, representation and behaviour as
either signed char or unsigned char. However it is still a distinct type
from both. That means for example

char *p1 = NULL;
signed char *p2 = p1;

is invalid even on implementations where char has a signed representation.


I don't understand what "invalid" means here.
Would a cast make it valid?
i.e.
char *p1 = NULL;
signed char *p2 = (signed char*)p1;
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?


Yes, it is the same.

Lawrence

Nov 14 '05 #4
On Tue, 21 Jun 2005 10:14:21 -0400, Stephen Mayes wrote:

"Lawrence Kirby" <lk****@netacti ve.co.uk> wrote in message
news:pa******** *************** *****@netactive .co.uk...
On Tue, 21 Jun 2005 08:57:10 +0200, Jason Curl wrote:
Dear C people,

C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
It says that char has the same range, representation and behaviour as
either signed char or unsigned char. However it is still a distinct type
from both. That means for example

char *p1 = NULL;
signed char *p2 = p1;

is invalid even on implementations where char has a signed representation.


I don't understand what "invalid" means here.


The code above violates a constraint in the standard which requires a
diagnostic from the compiler.
Would a cast make it valid?
Possibly. However that's digressing from the point I was making. If char
was allowed to be the *same* type as signed char then on implementations
where this was so the code above would be valid. However C says that the
types are always different even if they use the same representation.

The situation is different to that of int vs. signed int which are the
same type. It is closer to int vs. long which are different types even on
implementations that use the same representation for both.
i.e.
char *p1 = NULL;
signed char *p2 = (signed char*)p1;


That's valid because you can always cast a null pointer to any other
pointer type.

Lawrence

Nov 14 '05 #5
"Jason Curl" <j_********@mot orola.com> wrote

C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?

char may be signed or unsigned, but this is a hangover from K and R and
shouldn't be of any interest to you. char holds a human-language character,
unsigned char an arbitrary byte, signed char is of limited use but you might
occasionally want a small signed integer.

As a concession to efficiency, characters '0'-'9' are always consecutive and
you might want to exploit this fact to convert numbers to and from text.
This is the only occasion in which the machine representation of a
particular character should normally affect your program.
Nov 14 '05 #6
Malcolm wrote:
"Jason Curl" <j_********@mot orola.com> wrote
C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?

char may be signed or unsigned, but this is a hangover from K and R and


That's what I originally thought. But there was another post that
suggested the defined range of char is 7 bits (0-127), and in newer
standards is different to 'signed char' and 'unsigned char'. As to what
standard this is, I wasn't sure by the reply post. Thinking about it
more, I don't quite believe this, as then the datatype specifies char to
be 7-bits and not 8-bits.
shouldn't be of any interest to you. char holds a human-language character,
unsigned char an arbitrary byte, signed char is of limited use but you might
occasionally want a small signed integer.
I'm interested in-so-far as I'm getting a diagnostic from a compiler for
a small piece of code like:

01 #include <stdio.h>
02 int ctest(char s)
03 {
04 if (s < 0 || s >= 128) {
05 printf("Out of range\n");
06 return 0;
07 } else {
08 printf("In range\n");
09 return 1;
10 }
11 }

file.c:4: warning: comparison is always false due to limited range of
data type

and I want to know if the compiler is generating a useless diagnostic in
this case (and I ignore it, or figure out how to turn it off), or if it
is a problem with my code.

So, if 'char' is either 'signed' or 'unsigned', line 3 should stay as it
is. This particular compiler I'm using I assume treats 'char' as 'signed
char'.
As a concession to efficiency, characters '0'-'9' are always consecutive and
you might want to exploit this fact to convert numbers to and from text.
This is the only occasion in which the machine representation of a
particular character should normally affect your program.


Not quite. I don't actually care about the text itself as humans don't
need to read it, and I'm treating it literally as a string of random
values. The range of the values concerns me as I'm using an array of
structures that's indexed by the character value itself. I'm defining
that array to be 128 elements and check that the 'char' is in the range
of 0 to 127 (for a Posix system) before using it to index that char.

And of course, the actual size of a char is defined to be 8 bits (or
more, but 8 in Posix), so I interpret this as I must check the 8th bit
somehow.

It seems a little waste of CPU cycles/code clarity to take the value,
typecast it to int (or assign it to an int), make the comparison, then
index the array with the int as to avoid the warning.

Thanks,
Jason.
Nov 14 '05 #7
On Wed, 22 Jun 2005 12:25:46 +0200, Jason Curl wrote:
Malcolm wrote:
"Jason Curl" <j_********@mot orola.com> wrote
C90 doesn't specify if 'char' is either 'signed char' or 'unsigned char'
leaving it to the implementation of the compiler. Has this changed for
C99, or is it still the same?

char may be signed or unsigned, but this is a hangover from K and R and


That's what I originally thought. But there was another post that
suggested the defined range of char is 7 bits (0-127),


That may be a matter of interpretation. However plain char is implemented,
it must always be able to represent values in the range 0 to 127. That is
the intersection of the minimum ranges of signed char (-127 to 127) and
unsigned char (0 to 255). But on an implementation it always has the same
range as either signed char or unsigned char on that implementation, so it
will always be able to represent some values outside the range 0 to 127.

In other words 0 to 127 are the only values you can *portably* store in a
char.
and in newer
standards is different to 'signed char' and 'unsigned char'.
Standard C has always made char a distinct type to signedchar and
unsigned char, but it has always been required to use the representation
of one or the other.

....
I'm interested in-so-far as I'm getting a diagnostic from a compiler for
a small piece of code like:

01 #include <stdio.h>
02 int ctest(char s)
03 {
04 if (s < 0 || s >= 128) {
05 printf("Out of range\n");
06 return 0;
07 } else {
08 printf("In range\n");
09 return 1;
10 }
11 }

file.c:4: warning: comparison is always false due to limited range of
data type

and I want to know if the compiler is generating a useless diagnostic in
this case (and I ignore it, or figure out how to turn it off), or if it
is a problem with my code.

So, if 'char' is either 'signed' or 'unsigned', line 3 should stay as it
is. This particular compiler I'm using I assume treats 'char' as 'signed
char'.


It probably has CHAR_MAX as 127 then. In that case the test s >= 128 must
always be false. The compiler is correct in what it is saying for that
implementation, but the code is also correct in terms of portability. For
implementations where char is unsigned it will be the S < 0 test that is
"always false". You could replace the whole test with:

if ((unsigned char)s >= 128) {

Because of the unique properties of unsigned char you can be sure that the
cast will convert any negative value of s to a value >= 128.

Lawrence

Nov 14 '05 #8

"Jason Curl" <j_********@mot orola.com> wrote

01 #include <stdio.h>
02 int ctest(char s)
03 {
04 if (s < 0 || s >= 128) {
05 printf("Out of range\n");
06 return 0;
07 } else {
08 printf("In range\n");
09 return 1;
10 }
11 }

file.c:4: warning: comparison is always false due to limited range of data
type

and I want to know if the compiler is generating a useless diagnostic in
this case (and I ignore it, or figure out how to turn it off), or if it is
a problem with my code.
It's a sort of useless diagnostic. What it is complaining about is that char
can never go above 128 (assuming signed 8 bit chars). It may also dislike
comparing an unsigned for less than zero (assuming unsigned chars). It
doesn't ahve the intelligence to realise that the test is potentially
meaningful on a different machine.

The way I would get rid of this is to convert s to an int. Make the function
take an integer as an argument. This is traditional in C; fgetc() and
fputc() work this way, for instance.
Not quite. I don't actually care about the text itself as humans don't
need to read it, and I'm treating it literally as a string of random
values. The range of the values concerns me as I'm using an array of
structures that's indexed by the character value itself. I'm defining that
array to be 128 elements and check that the 'char' is in the range of 0 to
127 (for a Posix system) before using it to index that char.

And of course, the actual size of a char is defined to be 8 bits (or more,
but 8 in Posix), so I interpret this as I must check the 8th bit somehow.
Using a char for indexing is possibly one of the exceptions to the rule that
the machine representation is irrelevant. Are you sure you want 128 buckets
indexed by ascii value and that the program might not be clearer, if a
little slower, if you indexed alphabetically on alphanumeric values?
Remember the program may break if you move to a non-ascii system.
It seems a little waste of CPU cycles/code clarity to take the value,
typecast it to int (or assign it to an int), make the comparison, then
index the array with the int as to avoid the warning.

Probably no code will be executed. The character is held in an integer wide
register, and if treated as a char variable the top bits are ignored.
Nov 15 '05 #9
Malcolm wrote:
"Jason Curl" wrote:

01 #include <stdio.h>
02 int ctest(char s)
03 {
04 if (s < 0 || s >= 128) {
05 printf("Out of range\n");
06 return 0;
07 } else {
08 printf("In range\n");
09 return 1;
10 }
11 }

file.c:4: warning: comparison is always false due to limited range
of data type


The way I would get rid of this is to convert s to an int. Make
the function take an integer as an argument. This is traditional
in C; fgetc() and fputc() work this way, for instance.


It's not quite as trivial as that: fgetc and fputc work with
unsigned char values (ie. 0 - UCHAR_MAX) always. It's not a
great interface IMHO. You would have to document whether the
function was meant to receive an int that came from a signed char,
or from an unsigned char (or make your function work with both).

Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
17000
by: wwj | last post by:
Hi ,all I want to know the difference between char a and char *p=new char and the difference between the heap and the stack ,and if the char a is corresponding to the stack in MEMORY,and char *p=new char is corresponding to the heap of MEMORY. Give me some hint. THANK YOU.
10
5144
by: David | last post by:
what's the differences between: int main(int argc,char* argv){ ... } and: int main(int argc,char** argv){ ...
24
3637
by: wwj | last post by:
Hi ,all I want to know the difference between char a and char *p=new char and the difference between the heap and the stack ,and if the char a is corresponding to the stack in MEMORY,and char *p=new char is corresponding to the heap of MEMORY. Give me some hint. THANK YOU.
5
2006
by: Hal Styli | last post by:
Hello, can anyone explain the difference between the above declarations and why anyone would stray from the first. Are the other 2 standard, couldnt find them in K&R2. Thanks, Hal.
5
3980
by: jab3 | last post by:
(again :)) Hello everyone. I'll ask this even at risk of being accused of not researching adequately. My question (before longer reasoning) is: How does declaring (or defining, whatever) a variable **var make it an array of pointers? I realize that 'char **var' is a pointer to a pointer of type char (I hope). And I realize that with var, var is actually a memory address (or at
10
15664
by: tinesan | last post by:
Hello fellow C programmers, I'm just learning to program with C, and I'm wondering what the difference between signed and unsigned char is. To me there seems to be no difference, and the standard doesn't even care what a normal char is (because signed and unsigned have equal behavior). For example if someone does this: unsigned char a = -2; /* or = 254 */
15
2034
by: T Koster | last post by:
Hi group, I'm having some difficulty figuring out the most portable way to read 24 bits from a file. This is related to a Base-64 encoding. The file is opened in binary mode, and I'm using fread to read three bytes from it. The question is though, where should fread put this? I have considered two alternatives, but neither seem like a good idea: In most cases, the width of a char is 8 bits, so an array of 3 chars
19
2130
by: arnuld | last post by:
i am trying to understand arrays and char. Stroustrup says, this a string literal: "this is a string literal" he says it is of type /const char/. he also says, because of keeping compatibilities with previous definitions of C & C++, it is also a CHAR POINTER a.k.a /char*/. however it is an error, which can not be caught at untill runtime, to modify a string literal using such pointer:
5
4575
by: rajm2019 | last post by:
hi all, i want to know that what is the actual difference b/w the character array & character pointer.then how u will get the addrees of a char array char str="be silent like u" char *p1="be eloquent r u" char *p2; p2=str;
8
3250
by: amphetaman | last post by:
Is there a safe (unlikely to cause overflows or segfaults) way to load a text file into a char ** array? I thought of using getline, but it needs a fixed-length string, and I don't know how many lines or characters per line the file has.
0
10356
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10161
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10098
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9958
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8986
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7506
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6743
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5523
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2890
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.