testing for non-negativity

A

An

Dear all,

I need to test the elements of an array of chars for non-negativity.
I've read the following: "On most architectures testing for
non-negativity can be done several bytes at a time." Is this possible
with C as well? Is there a function to do so? First, I thought I
could use the function memchr, but this is not specific for
non-negativity and I'm not aware if it searches several bytes at a
time. I hope someone can help me out....

Kind regards and thanks in advance,

An
 
D

Daniel Fischer

An @ 2004-07-14:
I need to test the elements of an array of chars for non-negativity.
I've read the following: "On most architectures testing for
non-negativity can be done several bytes at a time." Is this possible
with C as well?

I'd imagine you could map the sign bit of a couple of chars into a
different type in order to check for any of them being one, which
would mean one of the elements is negative.

However the machine independent solution does not gain anything
over a straight implementation, except if you're using a very
intelligent compiler, but relying on a specific compiler wouldn't
be independent anymore so...



A machine dependent solution, which I'm posting for the purely
academic reason of informing people what they shouldn't do, could
look similar to this:

if(*(unsigned short *)(a+i) & 0x8080)
 
P

Peter Nilsson

Daniel Fischer said:
An @ 2004-07-14:

Note that plain char need not be signed.
I'd imagine you could map the sign bit of a couple of chars into a
different type in order to check for any of them being one, which
would mean one of the elements is negative.

However the machine independent solution does not gain anything
over a straight implementation, except if you're using a very
intelligent compiler, but relying on a specific compiler wouldn't
be independent anymore so...

A machine dependent solution, which I'm posting for the purely
academic reason of informing people what they shouldn't do, could
look similar to this:

if(*(unsigned short *)(a+i) & 0x8080)

You can easily confirm specifics and choose either coarse at your leisure. The only
difficulty is assuming the buffer to be scanned is suitably aligned for the longer type,
but that can be resolved with c/re/malloc().

#include <string.h>
#include <limits.h>

/*
// precondition: p is aligned for unsigned long
*/
int negative_present(const signed char *p, size_t n)
{
/*
// unpadded twos complement signed char?
*/
if (SCHAR_MAX - (unsigned) SCHAR_MIN == UCHAR_MAX)
{
unsigned long ul;
size_t i;

for (ul = -1, i = 1; i < sizeof ul; i++)
ul = ul >> (CHAR_BIT - 1) >> 1;

/*
// unpadded unsigned long?
*/
if (ul == UCHAR_MAX)
{
const unsigned long *ulp = (const unsigned long *) p;
signed char sc[sizeof ul];

for (i = 0; i < sizeof sc; i++)
sc = SCHAR_MIN;

memcpy(&ul, sc, sizeof ul);

i = n / sizeof ul;
n -= i * sizeof ul;

while (i--)
if (*ulp++ & ul)
return 1;

p = (const signed char *) ulp;
}
}

while (n--)
if (*p++ < 0)
return 1;

return 0;
}

I'm not saying it should be done (or should be done this way), merely that it can be done.
 
A

Alex Fraser

Peter Nilsson said:
Note that plain char need not be signed.


You can easily confirm specifics and choose either coarse at your
leisure. The only difficulty is assuming the buffer to be scanned is
suitably aligned for the longer type, but that can be resolved with
c/re/malloc().

And better resolved by casting the pointer to a suitable integer type and
checking its alignment. Since the method is platform-specific already, you
might as well.

Alex
 
S

SM Ryan

One way is strcmp(newsgroup,"comp.lang.c")!=0

(e-mail address removed) (An) wrote:
# Dear all,
#
# I need to test the elements of an array of chars for non-negativity.
# I've read the following: "On most architectures testing for
# non-negativity can be done several bytes at a time." Is this possible
# with C as well? Is there a function to do so? First, I thought I
# could use the function memchr, but this is not specific for
# non-negativity and I'm not aware if it searches several bytes at a
# time. I hope someone can help me out....

For an eight-bit byte twos complement, you can do
(0x80&character)!=0
Depending on alignment and integer sizes, you can do
(0x8080808080808080 & ((long long*)string))!=0
but this is a machine dependent solution. You can construct the
0x80...80 constant and some of the other details by consulting
sizeof and limits.h, but much of this remains machine dependent.
 
J

Jack Klein

An @ 2004-07-14:

I'd imagine you could map the sign bit of a couple of chars into a
different type in order to check for any of them being one, which
would mean one of the elements is negative.

However the machine independent solution does not gain anything
over a straight implementation, except if you're using a very
intelligent compiler, but relying on a specific compiler wouldn't
be independent anymore so...



A machine dependent solution, which I'm posting for the purely
academic reason of informing people what they shouldn't do, could
look similar to this:

if(*(unsigned short *)(a+i) & 0x8080)

No, it is not machine dependent as far as C is concerned. It is
undefined behavior to access objects with an lvalue of a different
type, with the exception of accessing any object as an array of
unsigned characters.

It could be doubly undefined if a+i does not have the proper alignment
for pointer to short.
 
A

Arthur J. O'Dwyer

Daniel Fischer said:
An @ 2004-07-14:
A machine dependent solution, which I'm posting for the purely
academic reason of informing people what they shouldn't do, could
look similar to this:

if(*(unsigned short *)(a+i) & 0x8080)

No, it is not machine dependent as far as C is concerned. It is
undefined behavior [...]

s/machine dependent/implementation dependent/ and his statement
is correct. Note that
"implementation-dependent" != "implementation-defined".

-Arthur,
from ghoulies and ghosties,
and long-leggedy beasties,
and language lawyers,
 
P

Peter Nilsson

Alex Fraser said:
And better resolved by casting the pointer to a suitable integer type and
checking its alignment. Since the method is platform-specific already, you
might as well.

The routine I showed had the same optimisation but was not dependant on implementation, so
I don't know why you're encouraging a line which is known to fail even for some twos
complement machines.
 

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
474,145
Messages
2,570,825
Members
47,371
Latest member
Brkaa

Latest Threads

Top