Set all bits to 1 in an array of raw bytes

P

pete

Martin said:
I have an array as follows:

char unsigned data[N];

I want to set every single bit in the array to 1. My initial thoughts
were:

memset(data, UCHAR_MAX, sizeof data);

but then when I looked at the declaration for memset, I saw that the
middle parameter was an int rather than an unsigned char. The problem
here is that UCHAR_MAX isn't guaranteed to "fit" in an int.

Can anyone think of a way to set all the bits to 1 (other than looping
through the elements and assigning UCHAR_MAX to them)?

Possibly, what I need is an int value that will convert to UCHAR_MAX
on every implementation... hmm...

memset(data, -1, sizeof data);

((unsigned char)-1) equals UCHAR_MAX.
The int argument value is converted to unsigned char by memset.

N869
7.21.6.1 The memset function
Synopsis
[#1]
#include <string.h>
void *memset(void *s, int c, size_t n);
Description
[#2] The memset function copies the value of c (converted to
an unsigned char) into each of the first n characters of the
object pointed to by s.
 
J

J. J. Farrell

But if you make something like that :
a = (char *) malloc (5 * 1)
instead
a = (char *) malloc (5 * sizeof (char))

you know that on some (strange) architectures (yes the standard are
not respected, but...) it doesn't work. It's sad, with the second one
it still work.

How can you possibly say that? If this mythical compiler differs from
a C compiler on something as fundamental to C as the size of char, how
can you assume that '=' does the same as in C, or that "malloc()" does
the same as in C?

Does the language compiled by this mythical compiler require the
result of malloc() to be cast? That's a bad practice in C.
 
P

pete

Martin said:
Mark:


Excuse me while I think out loud...

1: 0

Type: int
Value: 0

2: ~0

Type: int
Value: Whatever all bits 1 is on this sytems (most likely -1
though)

3: (char unsigned)~0

Type: int
Value: ...I think we've already gone implementation defined.

(~0) is implementation defined.
 
K

Keith Thompson

CBFalconer said:

That's a pre-C99 draft, unlike N1256, which has a great deal more
official standing. The only advantage of n869_txt.bz2 is that it's a
(compressed) plain text document. I strongly recommend using N1256
unless you have a *very* good reason for needing plain text rather
than PDF. There are small but significant differences between n869
and the official standard.

Chuck, it would be kind of you to mention this when you recommend
n860.
 
K

Keith Thompson

# 6.5.3.4 The sizeof operator
...
# Semantics
...
# 3 When applied to an operand that has type char, unsigned char, or
# signed char, (or a qualified version thereof) the result is 1.

Are you perhaps related to our other regular Frenchman? Your
idiosyncratic view of the language seems a match for his.

Note that Richard was referring to your idiosyncratic of C, not of
English.
 
K

Keith Thompson

But if you make something like that :
a = (char *) malloc (5 * 1)
instead
a = (char *) malloc (5 * sizeof (char))

you know that on some (strange) architectures (yes the standard are
not respected, but...) it doesn't work. It's sad, with the second one
it still work.

You are mistaken. The above can be written as

a = malloc(5);

and it's *absolutely guaranteed* to be equivalent to

a = malloc(5 * sizeof(char));

Not all compilers are 100% conforming, but making sizeof(char)
anything other than 1 just isn't an error any compiler write is going
to make. If sizeof(char) != 1, it's not C; it's about as likely as
2 + 2 != 4.

Really.
 
R

Richard

Keith Thompson said:
That's a pre-C99 draft, unlike N1256, which has a great deal more
official standing. The only advantage of n869_txt.bz2 is that it's a
(compressed) plain text document. I strongly recommend using N1256
unless you have a *very* good reason for needing plain text rather
than PDF. There are small but significant differences between n869
and the official standard.

You have the patience of Jobe. I come and go in this group but I
must have seen you mention this 20 gazillion times to the same person.
Chuck, it would be kind of you to mention this when you recommend
n860.

Kind? It would be the professional and right thing. Don't hold your
breath.
 
B

Barry Schwarz

unsigned char all1bit (void)
{
unsigned char a, b, c;
do
{
a = 2 * b + 1;

At this point, you have invoked undefined behavior the first time
through the loop.
c = a;
a = b;
b = c;
} while (a != b);
return a;
}

Perhaps this. But I'm not sure.
all1bit () must return a char with all bit set to 1. (You can use it
with every type, not just unsigned char, just rewrite the function).
After you copy it every where in your array.


Remove del for email
 
B

Barry Schwarz

Martin Wells said:
I have an array as follows:

char unsigned data[N];

I want to set every single bit in the array to 1. My initial thoughts
were:

memset(data, UCHAR_MAX, sizeof data);

but then when I looked at the declaration for memset, I saw that the
middle parameter was an int rather than an unsigned char. The problem
here is that UCHAR_MAX isn't guaranteed to "fit" in an int.

Why is that? Are you telling us that the standard says that an int can
be smaller than UCHAR? Since the smallest addressable unit of memory is a
byte and memset sets bytes, then surely an int will be bigger or
smaller than a byte and therefore -1 in an int in twos complement will
always be all bits set?

CHAR_BIT is not prohibited from being 16 or larger. On those systems
where sizeof(int) is one, it is possible for UCHAR_MAX to be the same
as UINT_MAX and both could be larger than INT_MAX.


Remove del for email
 
B

Barry Schwarz

When I code I don't assume that sizeof (char) == 1 and I'll never
assume it.

Let's see now -

In this post, you refuse to accept things the standard says
must be true.

In a previous post, you had no trouble assuming things the
standard says cannot be true.

In a third post, you dismissed the idea that you needed to
learn the basics of the language.

Not really the best approach for obtaining help here. All in all, you
give every appearance of being a troll. Don't be surprised if the
only responses to your messages are ones telling newcomers to the
language what is wrong with your code.


Remove del for email
 
A

Army1987

3: (char unsigned)~0

Type: int
Value: ...I think we've already gone implementation defined.
If int is two's complement, ~0 will be -1, so it'll become
UCHAR_MAX. OTOH, if it is ones' complement is is zero and will stay
zero, and if it is sign-and-magnitude it'll be -INT_MAX, which I
guess will be converted to 1.
 
A

Army1987

I have an array as follows:

char unsigned data[N];

I want to set every single bit in the array to 1. My initial thoughts
were:

memset(data, UCHAR_MAX, sizeof data);

but then when I looked at the declaration for memset, I saw that the
middle parameter was an int rather than an unsigned char. The problem
here is that UCHAR_MAX isn't guaranteed to "fit" in an int.

Can anyone think of a way to set all the bits to 1 (other than looping
through the elements and assigning UCHAR_MAX to them)?

Possibly, what I need is an int value that will convert to UCHAR_MAX
on every implementation... hmm...
memset(data, -1, sizeof data);
memset will convert the second parameter to unsigned char, which
is guaranteed to yield UCHAR_MAX.
 
I

iesvs

At this point, you have invoked undefined behavior the first time
through the loop.

No, the value of a and b is undefined, not the behavior. This is a
function who converges for any initial values of b. But if you want I
can give you 256 different codes, each one with a different value for
b. And I claim that, with some hypothesis (a, b, and c are in base 2,
they have a number of digits fixed, * 2 shift the bits, +1 put the new
one to 1 etc.), they will produce the same result.

So it's a well defined behavior.
 
I

iesvs

Note that Richard was referring to your idiosyncratic of C, not of

Explain, I'm curious.

And for the story of sizeof (char), why do you want to bridle the C ?
It's a wonderful language, you can respect the standard and produce a
valid code for compilers who don't respect standard (there are limits,
of course). C is a low-level language and a high-level, it makes
polymorphic, type checking (I never understand why some argue the
opposite).

I put the (char *) before malloc because it's not type correct in my
opinion to make (void *) == (char *). Now it doesn't echo warning (so
error) when I omit it, but in past it did. Perhaps it's because I
can't put -traditional to gcc (I remember that I did it in past, but
I'm not sure).
 
R

Ralf Damaschke

Mark said:
I don't think so. I think the section on "Representation of
types" in the standard will cover this.

Mostly. With "Unary arithmetic operators" and the section named
above we have: 2's complement ~0 is -1, 1's complement ~0 is 0
(may be negative zero) and sign/magnitude ~0 is INT_MIN.
Additionally taking "Signed and unsigned integers [conversions]"
into account (unsigned char)~0 will be UCHAR_MAX, 0 (unless ~0
is a trap representation) or 1, respectively.

So the result truely depends on "Representation of types" which
actually is implementation-defined.

Ralf
 
R

Richard Heathfield

(e-mail address removed) said:
No, the value of a and b is undefined, not the behavior.

See page 490 of ISO/IEC 9899:1999 for a summary of why you are wrong. Then
chase the references.
 

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,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top