Is it good to use char instead of int to save memory?

D

Dr Malcolm McLean

I would create a macro USMALL in a header file, and then define your small
numbers using:

USMALL c;


#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.


eg
void zeroduplicates(UBIG *x, USMALL N)
{
USMALL i;
for(i=0;i<N-1;i++)
if(x == x[i+1])
x = 0;
}

it's hard to spot the bug.
 
K

Keith Thompson

I would create a macro USMALL in a header file, and then define your small
numbers using:

USMALL c;

On an computer types where using a char datatype is more efficient (such as
on IBM compatible computers) the header file would define USMALL as follows:

#define USMALL unsigned char

(ie an unsigned char would be used)

On a platform where this produces overheads, the header file would define
USMALL as follows:

#define USMALL unsigned int

This would enable your code to be used portably on both platform types.

I'd use a typedef rather than a #define.

That's exactly what C99's uint_fast8_t is for (and uint_fast16_t and
so forth).
 
R

Richard Bos

Dr Malcolm McLean said:
On 20 Mar, 13:08, (e-mail address removed) (Mark Hobley)
#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.

void zeroduplicates(UBIG *x, USMALL N)
{
USMALL i;
for(i=0;i<N-1;i++)
if(x == x[i+1])
x = 0;
}

it's hard to spot the bug.


Pray tell. It's so hard to spot that I can't spot it.

(Not that I'd do that myself. I'd use a more descriptive name, _if_ I
found a typedef necessary at all, and by preference get (or under C89,
copy) one from <stdint.h>.)

Richard
 
E

Eric Sosman

Dr Malcolm McLean said:
On 20 Mar, 13:08, (e-mail address removed) (Mark Hobley)
#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.

void zeroduplicates(UBIG *x, USMALL N)
{
USMALL i;
for(i=0;i<N-1;i++)
if(x == x[i+1])
x = 0;
}

it's hard to spot the bug.


Pray tell. It's so hard to spot that I can't spot it.


zeroduplicates(pointer, 0);
 
D

Dr Malcolm McLean

On 20 Mar, 13:08, (e-mail address removed) (Mark Hobley)
#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.
void zeroduplicates(UBIG *x, USMALL N)
{
   USMALL i;
   for(i=0;i<N-1;i++)
     if(x == x[i+1])
       x = 0;
}
it's hard to spot the bug.

Pray tell. It's so hard to spot that I can't spot it.

        zeroduplicates(pointer, 0);

That's always a difficult one. It's harder to spot when a user-defined
type is used. Although the "U" in USMALL should give us a reminder
that the type is unsigned, it's easy to overlook that.
 
R

Richard Bos

Eric Sosman said:
Dr Malcolm McLean said:
On 20 Mar, 13:08, (e-mail address removed) (Mark Hobley)
#define USMALL unsigned int

The problem with that is that the code rapidly becomes almost
unreadable.

void zeroduplicates(UBIG *x, USMALL N)
{
USMALL i;
for(i=0;i<N-1;i++)
if(x == x[i+1])
x = 0;
}

it's hard to spot the bug.


Pray tell. It's so hard to spot that I can't spot it.


zeroduplicates(pointer, 0);


That's not a bug that was introduced, or IMO made harder to spot, by the
typedefs/defines. In fact, it may not be a bug at all. It could easily
be part of the preconditions for this function that N be at least 2.
It's no more nor less a bug _in this function_ than

zeroduplicates(null_pointer, 42);

or

zeroduplicates(array_of_10_UBIGs, 14);

Richard
 
D

Dr Malcolm McLean

Eric Sosman said:
On 20 Mar, 13:08, (e-mail address removed) (Mark Hobley)
#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.
void zeroduplicates(UBIG *x, USMALL N)
{
   USMALL i;
   for(i=0;i<N-1;i++)
     if(x == x[i+1])
       x = 0;
}
it's hard to spot the bug.
Pray tell. It's so hard to spot that I can't spot it.

   zeroduplicates(pointer, 0);

That's not a bug that was introduced, or IMO made harder to spot, by the
typedefs/defines. In fact, it may not be a bug at all. It could easily
be part of the preconditions for this function that N be at least 2.
It's no more nor less a bug _in this function_ than

  zeroduplicates(null_pointer, 42);

or

  zeroduplicates(array_of_10_UBIGs, 14);

Let's say that, for some reason, the function crashed when passed 15
as the number of dupicates. Of course we could document this and
claim that the fucntion was bug free. But in the absence of any
documentation, you assume that if input is valid, the function will
work. A list of no members is usally considered valid.
The bug could easily have been introduced by a typedef.
typedef char USMALL;

"Oh oh", someone realises, on this platform char is signed (but in
fact none of the integers go above 100).
Better make that
typedef unsigned char USMALL;

Bang.
 
R

Richard Bos

Dr Malcolm McLean said:
The bug could easily have been introduced by a typedef.
typedef char USMALL;

So, basically you're complaining that people can give typedefs imbecilic
names? Wooohooo, what a massive hole you've discovered! No wonder you're
now a doctor! Better get working on identifier names as well; before you
know it someone writes

unsigned int plus_or_minus;

and then you'll have an even worse bug.

Richard
 
S

Squeamizh

So, basically you're complaining that people can give typedefs imbecilic
names? Wooohooo, what a massive hole you've discovered! No wonder you're

Discovering massive holes must really excite you.
now a doctor! Better get working on identifier names as well; before you
know it someone writes

  unsigned int plus_or_minus;

and then you'll have an even worse bug.

You're a damned idiot.
 
D

Dr Malcolm McLean

So, basically you're complaining that people can give typedefs imbecilic
names?
That's one possibility. Another is that plain char is guaranteed to be
faster or as fast as unsigned char on the particular set of platforms
for which we target the code. Since USMALLs never go above 100, it is
reasonable to make them chars, whilst giving them the U prefix to
document that they are unsigned. Target platform now changes to one on
which unsigned char is faster than signed char, so it's a simple case
(they think) of redoing the typedef and the code doesn't need to be
rewritten.
Not all people who make poor decisions do so for reasons of
imbecility.
 
T

Tim Rentsch

dspfun said:
Hi,

Is it recommended to use char instead of int for variables that you
know never will contain a value larger than 255? A small example
follows:

#include <stdio.h>
int main(void)
{
//int i = 1;
char i = 1; //is this better than previous line?
printf("i=%d\n",i);
return 0;
}

What are the pros and cons of using char instead of int when values
will not exceed 255?

As a general rule it's better to use 'int' or 'unsigned int' (or
wider) than any narrower type such as 'short' or 'char' (or the
unsigned variants of those). There are two reasons for this
general rule. One, the behavior upon use in computation is often
unexpected and sometimes surprising. Two, usually the savings in
data and/or code size is either small, non-existent, or negative
(and ditto for speed). Also, it depends on what kind of variable
you're talking about -- it's almost always a bad idea to use a
type like 'short' or 'char' for a simple parameter or automatic
variable (here simple means scalar, ie, not arrays or members of
structs/unions).

Understanding that the general rule is right a lot more often
than it's wrong, here are some more-or-less standard
counterexamples --

arrays when the arrays are large

members of struct or union types, when
a) there will be lots of the outer struct/union type
b) the exact layout is constrained for some other reason

specific resource limitations or constraints, eg,
a) extremely limited global data space
b) extremely limited stack space
c) trading code space for data space or vice versa
d) trading speed for space or vice versa

using a narrow type can enforce a desired range limit, eg
a) an index to a 256 element array (and CHAR_BIT == 8)
b) similarly for arrays with 65,536 elements
c) want to do some computations modulo 256 or 65536
(which happens "for free" by storing into 'unsigned
char' or 'unsigned short' variables)

Notice that the kinds of considerations that go into the
different counterexamples are often quite different from
one to another.

Hopefully this outlines gives you a good sense of the
"shape" of the pros/cons you're looking for, and will
let you make better decisions when new cases come up.

Also, one other consideration, which is code evolution. In the
particular case you give above, it may be short sighted to use
'char' because "you know it will never contain a value larger
than 255". Perhaps that's true for the code as it is today, but
who knows how the code might change tomorrow? Unless there are
definite reasons for believing a particular value will _never_ be
exceeded, it's usually better to expect that it will.
 
T

Tim Rentsch

Dr Malcolm McLean said:
I would create a macro USMALL in a header file, and then define your small
numbers using:

USMALL c;


#define USMALL unsigned int
The problem with that is that the code rapidly becomes almost
unreadable.


eg
void zeroduplicates(UBIG *x, USMALL N)
{
USMALL i;
for(i=0;i<N-1;i++)
if(x == x[i+1])
x = 0;
}

it's hard to spot the bug.


The problem here is with the function body, not the choice of
type name. Right off the bat, it's a mistake to use a type of
unknown signedness/promotion characteristics in arithmetic
computation; the parameter 'N' may be forced to be of type
USMALL, but not 'i'. And the comparand 'N-1' is obviously
fraught with peril.

Besides type conversion problems, writing the comparison 'i<N-1'
is suspect because it expresses the desired relationship
less directly than it could. We're indexing 'x' by 'i+1';
hence what we want is 'i+1<N'. Even if the types chosen
are left as is, this change eliminates the corner case.

Hard to spot the bug? Not hard at all -- the bug is
that the code should never have made it out of code
review.
 
D

Dr Malcolm McLean

Dr Malcolm McLean said:
void zeroduplicates(UBIG *x, USMALL N)
{
  USMALL i;
  for(i=0;i<N-1;i++)
    if(x == x[i+1])
      x = 0;
}

it's hard to spot the bug.

Hard to spot the bug?  Not hard at all -- the bug is
that the code should never have made it out of code
review.

I've nothing against code reviews. As you say, review ought to pick up
mistakes like this. But not everyone does reviews, and the reviews are
only as good as the people doing the reviewing. (In practice they
don't eliminate all bugs, or the software crisis would be solved).

If you tell someone that a four-line fragment of code has a bug, and
they fail to spot it, I think we can reasonably conclude that the bug
is hard to spot.
 
T

Tim Rentsch

Dr Malcolm McLean said:
Dr Malcolm McLean said:
void zeroduplicates(UBIG *x, USMALL N)
{
  USMALL i;
  for(i=0;i<N-1;i++)
    if(x == x[i+1])
      x = 0;
}

it's hard to spot the bug.

Hard to spot the bug?  Not hard at all -- the bug is
that the code should never have made it out of code
review.

I've nothing against code reviews. As you say, review ought to pick up
mistakes like this. But not everyone does reviews, and the reviews are
only as good as the people doing the reviewing. (In practice they
don't eliminate all bugs, or the software crisis would be solved).

If you tell someone that a four-line fragment of code has a bug, and
they fail to spot it, I think we can reasonably conclude that the bug
is hard to spot.


The reason I find this argument unconvincing is that the code
was constructed deliberately to make the bug hard to spot.
Personally I don't need to see the 'i<N-1' at all to find
reasons to raise objections (or at least questions), but
that's beside the point. The argument was based on a
strawman example, and generally such arguments aren't
convincing. You see my point?
 
B

blmblm

[ snip ]
Veteran readers of comp.lang.c will have noticed a change in my
moniker. I'm Dr Malcolm McLean now.

Belated but hearty congratulations!!!! [*] I noticed the change
but assumed it was because you had decided for some reason to draw
attention to your title. It didn't occur to me that perhaps you
had just earned the right to use the title. (I think this may
be a compliment of sorts.)

[*] Normally four exclamation points would be excessive and bad
style. Here, though, I think they're just right.
 
H

Herbert Rosenau

or this

unsigned char ch;

while( (ch = fgetc(fp)) != EOF )

This is designed to create trouble at all!

fgetc returns int, not char.
EOF is an int, not a char.

So you'll fails always to see that the file readed completely because
(char) EOF is noways comperable with EOF because significant bits are
lost by assigning the result of fgetc() to a char instead of int.
/* do something */;

or this

unsigned char exponent;
double mantissa;

mantissa = frexp(x, &exponent);


Nonsense because exponent is signed, not unsigned. There is no
guarantee that exponent is not wider than a single char contains bits.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
H

Herbert Rosenau

- You are near the resources of the processor.

On some processors using int data types increases code size and execution time
over char data types. You are normally aware if that is so.
No, because int is the natural wide of the processor. handling int
will always produce the most possible code because C is designed to
use int to get best.

char on other hand is implementation defined either unsigned or
signed, so if you only defines char without explicite type specifier
signed or unsigned it will give you unwanted behavior when you changes
the implementation or simply only the version of it.

There are processors alive where access to a char costs significant
more runtime and or extra instructions because the processor is unable
to access a single char in memory and must truncate and expand single
chars to/from int in memory.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top