What is wrong with this c-program?

  • Thread starter Albert van der Horst
  • Start date
S

Seebs

No? If you had to make an educated guess as to the number of bits in a
'byte' type, and your life depending on it, what would be your best guess;
11?

My best *guess* would be 8, but I would hate to rely on that, because
it's sometimes wrong.
Anyway, if the width of a 'byte' type alias in C source code is ambiguous,
then so is the width of a 'char' type.

Sure. But at least I know for sure what a char *is*. I can't be as confident
that I know what someone meant when they called something a "byte".

-s
 
K

Keith Thompson

BartC said:
Noob said:
BartC said:
'byte' [...] is a lot shorter (and easier on the eye) than 'uint8_t'.
And it explains more, because everyone knows what a byte is.

No. Use "octet" if you need a word for uint8_t, not "byte".
"byte" is a pun on "bit/bite". It conveys no size information.

No? If you had to make an educated guess as to the number of bits in a
'byte' type, and your life depending on it, what would be your best guess;
11?

No, CHAR_BIT.

[...]
 
J

Jorgen Grahn

I'm not sure that's necessarily it. Weinberg ("The Psychology of
Computer Programming") describes the same attitude, even amongst some
supposedly "professional" (and experienced) programmers, way back in
the 60s.

My practical experience, too, today. Although the /very/ experienced
can see that it's unlikely that a widely used version of gcc, for a
popular target and with commonly used flags has spectacular bugs.

/Jorgen
 
J

Jorgen Grahn

Noob said:
BartC said:
'byte' [...] is a lot shorter (and easier on the eye) than 'uint8_t'.
And it explains more, because everyone knows what a byte is.

No. Use "octet" if you need a word for uint8_t, not "byte".

"byte" is a pun on "bit/bite". It conveys no size information.

Except in the real world of course where pretty much everyone uses it to
refer to 8 bits. But yes, you're right...

Pretty much everyone use machines where octet, byte, uint8_t and char
are the same thing modulo signedness. But when you're writing C code
you have to acknowledge that it may be compiled for a machine where
this isn't true ... or somehow make it clear that you don't intend to
support exotic architectures.

/Jorgen
 
I

Ian Collins

Jorgen said:
Noob said:
BartC wrote:

'byte' [...] is a lot shorter (and easier on the eye) than 'uint8_t'.
And it explains more, because everyone knows what a byte is.

No. Use "octet" if you need a word for uint8_t, not "byte".

"byte" is a pun on "bit/bite". It conveys no size information.

Except in the real world of course where pretty much everyone uses it to
refer to 8 bits. But yes, you're right...

Pretty much everyone use machines where octet, byte, uint8_t and char
are the same thing modulo signedness. But when you're writing C code
you have to acknowledge that it may be compiled for a machine where
this isn't true ... or somehow make it clear that you don't intend to
support exotic architectures.

Well uint8_t will be consistent (if present), so you may as well use it.
 
J

Jorgen Grahn

I have the following program that gives consistently a segfault
with
--------------------
46344 1
46345 1
46346 1
46347 1
46348 1
46349 0
Segmentation fault

I get four warnings when compiling it (also on Debian stable, good
choice by the way) and one hint from valgrind when it segfaults.
(Valgrind doesn't give more information than a core dump would have in
this case though.)
It is a classical prime sieve.
I can't find any fault with it.

Use the few troubleshooting tools which are available to you; it frees
up your brain for more important tasks.
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

#define BYTE uint8_t

/* largest number */
#define MAXSIZE 20000000
#define SIZE 2000000

long int TheLimit;

/*****************************************************************************/
/* */
/* Fill the `nprimes' table up to `n' */
/* */
/*****************************************************************************/


static BYTE composite[ MAXSIZE+1];

void fill_primes( int n)
{
int i,j;

assert(n<=MAXSIZE);
for (i=0;i<=n; i++) composite = 0;
for ( i=2; i<=n; i++)
{
printf("%d %d \n",i,composite);
if (!composite)
{
for (j=i*i; j<=n; j+=i) composite[j] = 1;
}
}
}

int main( int argv, char** argc)


sun.c:38:15: warning: unused parameter 'argv'

You have reversed the meanings of argv and argc -- "v" is for "vector"
and "c" is for "count". Not a bug, but unusual and confusing!

sun.c:40:9: warning: unused variable 'i'
TheLimit = atoi(argc[1]);

sun.c:41:5: warning: implicit declaration of function 'atoi'
printf("n= %d\n",TheLimit);

sun.c:42:5: warning: format '%d' expects argument of type 'int', but
argument 2 has type 'long int'
fill_primes(TheLimit);
printf("primes ready\n");
}

/Jorgen
 
J

Jorgen Grahn

(e-mail address removed)4all.nl (Albert van der Horst) writes: ....

Others have pointed out lots of errors. Here's one of the biggest and
one no compiler can protect you against: a stonking great comment that
doesn't actually tell you much and - crucially - what it tells you is
wrong: there is no nprimes table.

Two observations of mine:
- The fresher the novice, the more elaborate comment blocks.
- The more elaborate the comment block, the less useful its content.

/Jorgen
 
D

David Brown

I stand corrected. I looked it up in N1570 and saw I was mistaken only
after I had sent the post. I blame the eggnog. :)


A good time to use the #error directive then, isn't it?

Nah, why clutter up the program with extra lines and #error directives
for a situation that almost certainly will not occur? Just use
"uint8_t" and let the compiler give an error that is marginally harder
to understand if you have a platform without 8-bit support.

Alternatively, use uint_least8_t, which will exist.

It seems to me that using "uint8_t" directly is more appropriate than a
macro /or/ a typedef. If you want to use a new type name here, then a
typedef to an appropriate name (such as "typedef uint8_t flag_t;") would
be more useful.
 
D

David Brown

My best *guess* would be 8, but I would hate to rely on that, because
it's sometimes wrong.


Sure. But at least I know for sure what a char *is*. I can't be as confident
that I know what someone meant when they called something a "byte".

I have used processors with 16-bit "char", and no way to make an 8-bit
type (except as a bitfield). Nowhere, in any of the documentation,
manuals, datasheets, or anywhere else was there any reference to a
"byte" that is not 8 bits. It made clear that a /char/ was 16 bits
rather than the usual 8 bits, but they were never called "bytes".

I haven't used such devices much - but the vast majority of people who
use the term "byte" have never even heard of such devices, never mind
used them.

There are only two situations when "byte" does not automatically and
unequivocally mean "8 bits" - one is in reference to ancient computer
history (and documents from that era, such as network RFC's), and the
other is extreme pedantry. There is a time and place for both of these
- but you won't convince many people that you would ever /really/ think
a reference to a "byte" meant anything other than 8 bits.

(If you can give modern, or at least still-current, references to usage
of "byte" for something other than 8 bits, then I will recant and blame
the egg nog!.)

A "char", as you say, has a well defined meaning - but not a well
defined size.
 
J

James Kuyper

On 12/29/2013 09:14 AM, David Brown wrote:
....
- but you won't convince many people that you would ever /really/ think
a reference to a "byte" meant anything other than 8 bits.

Why should it be so hard to convince people of that? I can imagine
having a hard time convincing people that "byte" means anything other
than 8 bits (obviously, that only applies to people who don't consider
the C standard authoritative) - however, why should it be difficult to
convince other people that *I* believe it to be true?
 
O

osmium

David Brown said:
I have used processors with 16-bit "char", and no way to make an 8-bit
type (except as a bitfield). Nowhere, in any of the documentation,
manuals, datasheets, or anywhere else was there any reference to a "byte"
that is not 8 bits. It made clear that a /char/ was 16 bits rather than
the usual 8 bits, but they were never called "bytes".

I haven't used such devices much - but the vast majority of people who use
the term "byte" have never even heard of such devices, never mind used
them.

There are only two situations when "byte" does not automatically and
unequivocally mean "8 bits" - one is in reference to ancient computer
history (and documents from that era, such as network RFC's), and the
other is extreme pedantry. There is a time and place for both of these -
but you won't convince many people that you would ever /really/ think a
reference to a "byte" meant anything other than 8 bits.

(If you can give modern, or at least still-current, references to usage of
"byte" for something other than 8 bits, then I will recant and blame the
egg nog!.)

A byte that is not 8 bits is indeed rare, but I am certain there has been
such usage in a more or less valid way. The 9-bit chunk on a Univac 11000
series for example. I note you stuck "modern" in there as a qualifier. To
refer to that system as a Unisys whatever (to modernize it), just obfuscates
things. This thread has a lot more to do with pedants inheriting the earth
than anything else. Or at least co.law.co.

In a similar vein, anyone who spells that hard rive thingy as a disc instead
of a disk is late to the party as far as I am concerned.
 
P

Phil Carmody

Jorgen Grahn said:
Two observations of mine:
- The fresher the novice, the more elaborate comment blocks.
- The more elaborate the comment block, the less useful its content.

I've thought various things along those lines in the past, but your
rendering of the concept is absolutely perfect!

Were there a list of C koans, that should be part of it.

Phil
 
P

Phil Carmody

Kinda-piggybacking, OP not visible to me.

Jorgen Grahn said:
I get four warnings when compiling it (also on Debian stable, good
choice by the way) and one hint from valgrind when it segfaults.
(Valgrind doesn't give more information than a core dump would have in
this case though.)


Use the few troubleshooting tools which are available to you; it frees
up your brain for more important tasks.

The brain might be the perfect tool for the job. A bug in the code jumped
out quicker than it would have taken me to copy/paste, compile, and run
under gdb.
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

#define BYTE uint8_t

/* largest number */
#define MAXSIZE 20000000
#define SIZE 2000000

long int TheLimit;

/*****************************************************************************/
/* */
/* Fill the `nprimes' table up to `n' */
/* */
/*****************************************************************************/


static BYTE composite[ MAXSIZE+1];

void fill_primes( int n)
{
int i,j;

assert(n<=MAXSIZE);
for (i=0;i<=n; i++) composite = 0;
for ( i=2; i<=n; i++)
{
printf("%d %d \n",i,composite);
if (!composite)
{
for (j=i*i;


BANG!!! i*i will be negative at some point.
A wild stab in the dark, some point around i=46349.

Possible solutions:
(1) Generally - Use unsigned integer types for things you know can never
be negative. (but take care to make sure those assumptions don't mess
things up, loops that count down can often cause newbs problems.)
(2) This particular case - Stop the sieving loop as soon as you're sure
that no more composites can be sieved out. So don't loop i up to n, loop
op to sqrt(n) instead, and then just dump the rest of the contents out
in a trivial loop without sieving.

Phil
 
P

Paul

Bill said:
"osmium" wrote in message news:[email protected]...

Always a chuckle when someone commenting on spelling spells something
wrong. So I probably will somewhere in here too.

We'll assume "hard rive" means "hard drive."

The spelling of name for a flat circular object is regional. "Disk" is
generally American usage whereas "disc" seems to be common other places.
I've heard the same lament, the other way around, from Europeans I've
worked with. Some just thought we were being provincial, others
considered our spelling to be barbaric. Similar comments about "color"
vs. "colour."

- Bill

Disc is used for optical media.
Disk is used for hard drives.

http://en.wikipedia.org/wiki/Disc

Magnetic disk
http://en.wikipedia.org/wiki/Disk_drive
"The choice... is frequently historical,
as in... "IBM 350 disk storage unit"."

Optical disc (i.e. discus/frisbee)
http://en.wikipedia.org/wiki/Frisbee
http://en.wikipedia.org/wiki/Discus

Paul
 
O

osmium

Bill Leary said:
"osmium" wrote in message news:[email protected]...

Always a chuckle when someone commenting on spelling spells something
wrong. So I probably will somewhere in here too.

We'll assume "hard rive" means "hard drive."

The spelling of name for a flat circular object is regional. "Disk" is
generally American usage whereas "disc" seems to be common other places.
I've heard the same lament, the other way around, from Europeans I've
worked with. Some just thought we were being provincial, others
considered our spelling to be barbaric. Similar comments about "color"
vs. "colour."

My mind set when I made my post. Disc is the proper US spelling for a disc,
say a Frisbee. But someone in IBM spelled it disk and it stuck so all
computer people should spell it disk. After all, IBM can do no wrong.

I just tried to verify what I thought I knew and the first response from
google for disc is disk! I don't think I have any paper dictionaries any
more but drilling down in google seems to verify my earlier thoughts. Google
was just "helping" me.
 
D

David Brown

On 12/29/2013 09:14 AM, David Brown wrote:
...

Why should it be so hard to convince people of that? I can imagine
having a hard time convincing people that "byte" means anything other
than 8 bits (obviously, that only applies to people who don't consider
the C standard authoritative) - however, why should it be difficult to
convince other people that *I* believe it to be true?

It's a matter of believability. Certainly some people believe in things
that others find unlikely, which is fair enough. But if you were to say
"I believe the moon is made of cheese", I would not believe that you
believe that. Obviously sticking to old-fashioned definitions of a term
like "byte" isn't quite that extreme - but if you say, without reference
or additional qualification, that you believe a reference to a "byte" in
current writing might reasonably refer to something other than 8 bits,
then I would not take you literally. I would assume you are
exaggerating, joking, playing the devil's advocate, or otherwise trying
to make a point in some way, or perhaps you have misread the question or
mistyped the answer. (But I certainly won't assume you are lying or
"trolling".) If you repeat your belief, I'll accept it - but until I
was sure, I'd assume there was some other explanation.

But I think this is getting a bit too philosophical - I'm off to watch
Mr. Bean's New Year :)
 
J

Jorgen Grahn

Jorgen Grahn said:
BartC wrote:

'byte' [...] is a lot shorter (and easier on the eye) than 'uint8_t'.
And it explains more, because everyone knows what a byte is.

No. Use "octet" if you need a word for uint8_t, not "byte".

"byte" is a pun on "bit/bite". It conveys no size information.

Except in the real world of course where pretty much everyone uses it to
refer to 8 bits. But yes, you're right...

Pretty much everyone use machines where octet, byte, uint8_t and char
are the same thing modulo signedness. But when you're writing C code
you have to acknowledge that it may be compiled for a machine where

You don't have to do anything of the kind. It doesnt take a genius to
assume the general truth when nothing else indicates otherwise.

I do understand the reasoning - however one must keep it real. A Byte is
8 bits in 99.99% of places and meeting rooms. If we must be pedantic
each and every time then that might be fine for c.l.c but not for most
people - for others its tiresome pedantry designed to irritate.

For me it's a matter of clarity. If there is a discussion and there's
a hidden assumption that a char is eight bits, which other assumptions
are there? The C standard is a help in this respect -- even though it
sometimes forces you to consider some rare special cases.
Or, and better, make it clear when you do.

ie this code is designed to be multi platform and support multiple byte
sizes.etc etc

Do you by chance have a Windows background? Mine is Unix. There it's
normal to try to write portable code, since there are so many
different processors in use, and you never know where your program
will end up running. Alignment restrictions, endianness, padding,
sizeof long ... those things change all the time[1].

That doesn't mean I always write portable code, or even document when
I don't. Not even when I break the subset of C determined by POSIX ...
but it's still my goal.

/Jorgen

[1] Not the CHAR_BIT aspect, though. IIRC POSIX requires an
architecture with 8-bit bytes.
 
J

James Kuyper

On 12/29/2013 03:32 PM, David Brown wrote:
....
It's a matter of believability. Certainly some people believe in things
that others find unlikely, which is fair enough. But if you were to say
"I believe the moon is made of cheese", I would not believe that you
believe that. Obviously sticking to old-fashioned definitions ...

I'm curious about your labeling of this definition as "old-fashioned". A
very large fraction of newly written C code is targeted to embedded
systems. I'm not sure how large that fraction is, but it's large enough
that, on one memorable occasion, I had considerable trouble convincing
one guy that it was less than 100%. Many of those embedded systems are
DSPs with 16 bit bytes. So implementations of C with bytes that are not
equivalent to octets is a very current issue.
... of a term
like "byte" isn't quite that extreme - but if you say, without reference
or additional qualification, that you believe a reference to a "byte" in
current writing might reasonably refer to something other than 8 bits,
then I would not take you literally.

So, you consider the definition of "byte" that is provided by the C
standard to be so thoroughly esoteric (is that the right word to cover
your objection?) that it would never occur to you that I might consider
that definition to be authoritative in the context of C code? Unless I
emphatically told you otherwise (as I am now doing), you:
... would assume you are
exaggerating, joking, playing the devil's advocate, or otherwise trying
to make a point in some way, or perhaps you have misread the question or
mistyped the answer. ...

That seems like a rather extreme position to take. It's as if you were
actively resisting learning the fact (and it IS a fact) that there are
contexts where some people use the term with a different definition from
the one you're used to.
 
K

Keith Thompson

Phil Carmody said:
BANG!!! i*i will be negative at some point.
A wild stab in the dark, some point around i=46349.

Possible solutions:
(1) Generally - Use unsigned integer types for things you know can never
be negative. (but take care to make sure those assumptions don't mess
things up, loops that count down can often cause newbs problems.)
(2) This particular case - Stop the sieving loop as soon as you're sure
that no more composites can be sieved out. So don't loop i up to n, loop
op to sqrt(n) instead, and then just dump the rest of the contents out
in a trivial loop without sieving.

But don't compute sqrt(n) each time through the loop. Computing sqrt(n)
can be moderately expensive, and is likely to swamp the time you save by
doing fewer iterations. Either compute sqrt(n) once at the top of the
loop and save it in a variable (and watch out for floating-point
rounding issues), or change the logic so you compare i*i vs. n rather
than comparing i vs. sqrt(n).
 

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
474,075
Messages
2,570,553
Members
47,197
Latest member
NDTShavonn

Latest Threads

Top