#include <stdio.h>
#include <ctype.h>
int main(void)
{
unsigned int c,j;
unsigned char k;
unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
void *s=(void*)buf;
for(c=0;c<=255;c++){
memset(s,0,sizeof(buf));
for(j=1,k=7;j<=256;j=j*2,k--){
if(c&j)
buf[k]='1';
else
buf[k]='0';
}
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s
\n",isprint((int)c)?c:'.',c,c,c,buf);
}
return 0;
}
Thank you
An aside on the question: you're not going to print ASCII with that,
you're going to print whatever is the code on your computer (which is
very likely (but not guaranteed - a few of us here have used EBCDIC
machines)) to be ASCII for part of the range, but you'll almost
certainly have some printable characters above 127 (where ASCII stops)
that will be displayed, and these are very likely to vary from operating
system to operating system (or even environments within a single OS on a
single physical machine).
That aside, I'm afraid the answer is no - there's no way to print a
value as binary in standard C. A lot of people have added a %b or
similar to printf but it's an extension and not always available. There
are lots of ways to convert to a binary representation and yours is as
good as anything. I'd be tempted to put it in a function - to make the
purpose of the loop (printing the values) more obvious.
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu
>Hello, I'm trying to write a code to print out ascii characters,
>and wondering if there is a more sophisticated way to print out binary
>data like "00100001". Now I'm using loop, but it looks ugly....
>
>#include <stdio.h>
>#include <ctype.h>
>
>int main(void)
>{
> unsigned int c,j;
> unsigned char k;
> unsigned char buf[9]={0,0,0,0,0,0,0,0,'\n'};
The initialization is useless since it is completely overwritten by
the memset below. In particular, the '\n' is lost. Which is actually
desirable since you want buf[8] to be 0 anyway.
> void *s=(void*)buf;
>
> for(c=0;c<=255;c++){
> memset(s,0,sizeof(buf));
Why bother with s when
memset(buf, 0, sizeof buf);
does the job just as well?
On the other hand, why bother at all since you replace all the values
except buf[8] with '0' or '1' below. Your best approach would be to
replace the initialization of buf with {0} and remove this.
> for(j=1,k=7;j<=256;j=j*2,k--){
On the first iteration, k=7, j=1.
Next k=6, j=2.
Next k=5, j=4.
Next k=4, j=8.
Next k=3, j=16.
Next k=2, j=32.
Next k=1, j=64.
Next k=0, j=128.
Next k=255, j=256 and your code below invokes
undefined behavior by attempting to access buf[255]. You are looping
one to many times.
> if(c&j)
> buf[k]='1';
> else
> buf[k]='0';
> }
> printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s
>\n",isprint((int)c)?c:'.',c,c,c,buf);
Don't you think a little horizontal white space would make this a lot
more readable?
> }
> return 0;
>}
>
>
>Thank you
--
Remove del for email
I would write that, this way:
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
void bit_str(char *s1, const void *s2, size_t n);
int main(void)
{
unsigned char c = 0;
char buf[sizeof c * CHAR_BIT + 1];
do {
bit_str(buf, &c, sizeof c);
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
isprint(c) ? c : '.' , c, c, c, buf);
} while (c++ != (unsigned)UCHAR_MAX);
return 0;
}
void bit_str(char *s1, const void *s2, size_t n)
{
const unsigned char *const byte = s2;
while (n-- != 0) {
unsigned mask = ((unsigned char)-1 >> 1) + 1;
do {
*s1++ = (char)(mask & byte[n] ? '1' : '0');
mask >>= 1;
} while (mask != 0);
}
*s1 = '\0';
}
--
pete
> for(j=1,k=7;j<=256;j=j*2,k--){
> if(c&j)
> buf[k]='1';
> else
> buf[k]='0';
> }
It's difficult to avoid using a loop. But you can put the code into a
function. As in the the following example, which converts an int value into
a string of "0"s and "1"s (and is always a fixed length, typically 32
characters):
#include <stdio.h>
#include <limits.h>
/* Convert value a into a string of zeros and ones at dest */
void str_bin(char *dest,int a) {
int n = sizeof(a)*CHAR_BIT;
int mask = 1;
dest[n]=0;
while (mask) {
dest[--n] = (a & mask ?'1':'0');
mask <<=1;
}
}
/* Usage: */
int main(void)
{
char str[100]; /* 33 or 65 at least */
int i=16385;
str_bin(str, i);
printf("Binary(%d) = %s\n",i,str);
}
--
Bartc
Yes, I was wrong about the range of ASCII characters. and did not know
that
the range of ASCII varies from OS to OS...
>
> That aside, I'm afraid the answer is no - there's no way to print a
> value as binary in standard C. A lot of people have added a %b or
> similar to printf but it's an extension and not always available. There
> are lots of ways to convert to a binary representation and yours is as
> good as anything. I'd be tempted to put it in a function - to make the
> purpose of the loop (printing the values) more obvious.
I see, I just wondered that if there exists some to do that, but good
to
know that I can't, Thanks.
> On Nov 20, 12:00 am, Nick <3-nos...@temporary-address.org.uk> wrote:
>> Yoshi <hirot...@gmail.com> writes:
>> > Hello, I'm trying to write a code to print out ascii characters,
>> > and wondering if there is a more sophisticated way to print out binary
>> > data like "00100001". Now I'm using loop, but it looks ugly....
[snip]
>>
>> An aside on the question: you're not going to print ASCII with that,
>> you're going to print whatever is the code on your computer (which is
>> very likely (but not guaranteed - a few of us here have used EBCDIC
>> machines)) to be ASCII for part of the range, but you'll almost
>> certainly have some printable characters above 127 (where ASCII stops)
>> that will be displayed, and these are very likely to vary from operating
>> system to operating system (or even environments within a single OS on a
>> single physical machine).
>
> Yes, I was wrong about the range of ASCII characters. and did not know
> that the range of ASCII varies from OS to OS...
No, it doesn't.
ASCII extends from 0x00 to 0x7f, regardless of operating system. /If/ you
wish to interpret values beyond 0x7f as characters, you must use some other
characterset other than ASCII.
[snip]
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
---------- Slackware - Because I know what I'm doing. ------
Thanks, now i see a lot bugs in my code.
Thanks, but I don't see why it's not like...
const unsigned char *byte = s2;
Could you explain why you used below?
Thanks, now I see there is no way to waive loop to print out the
contents of data in binary format...
>> while (mask) {
>> dest[--n] = (a & mask ?'1':'0');
>> mask <<=1;
>> }
> Thanks, now I see there is no way to waive loop to print out the
> contents of data in binary format...
If you just want to print (8-bit) char values, then you can just have an
array of 256 strings:
char *table[256] = {"00000000","00000001",..."11111111"};
then use an array to convert:
printf("%s",table[123]);
To convert integers, you can still use the same table, using 4 (or 8)
successive strings from the table, without using a loop.
But this will all take extra space (and lots of typing), while having a loop
is not really a big deal.
--
Bartc
The second const is a promise that 'byte' will not be changed. The
code has the same effect without it but the const gives more
information.
<snip>
--
Ben.
> Yoshi wrote:
>> On Nov 20, 4:49 am, "bartc" <ba...@freeuk.com> wrote:
>>> "Yoshi" <hirot...@gmail.com> wrote in message
>>> news:d66d7619-08a8-4ccf...@j9g2000prh.googlegroups.com...
>>>
>>>> Hello, I'm trying to write a code to print out ascii characters,
>>>> and wondering if there is a more sophisticated way to print out
>>>> binary data like "00100001". Now I'm using loop, but it looks
>>>> ugly.... for(j=1,k=7;j<=256;j=j*2,k--){
>
>>> while (mask) {
>>> dest[--n] = (a & mask ?'1':'0');
>>> mask <<=1;
>>> }
>
>> Thanks, now I see there is no way to waive loop to print out the
>> contents of data in binary format...
>
> If you just want to print (8-bit) char values, then you can just have
> an array of 256 strings:
>
> char *table[256] = {"00000000","00000001",..."11111111"};
...or a table of unsigned longs:
unsigned long table[256] = { 0x0, 0x1, ... 0x11111111 };
> then use an array to convert:
>
> printf("%s",table[123]);
...with printf("%08lx", table[123]);
I think a good compromise between table size and looping is to use
unsigned shorts from 0 to 0x1111 and to print 4 bits at a time.
<snip>
--
Ben.
Thanks for the suggestions, asides, I just come up with the following
code that does not use loop, though not sure it's portable.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
typedef union _mychar{
char c;
struct{
unsigned short seven: 1;
unsigned short six: 1;
unsigned short five: 1;
unsigned short four: 1;
unsigned short three: 1;
unsigned short two: 1;
unsigned short one: 1;
unsigned short zero: 1;
}bit;
}mychar;
int main(void)
{
mychar b;
unsigned int c;
unsigned char buf[CHAR_BIT];
for(c=0;c<=127;c++){
b.c = c;
buf[0] = (b.bit.zero) ?'1':'0';
buf[1] = (b.bit.one ) ?'1':'0';
buf[2] = (b.bit.two ) ?'1':'0';
buf[3] = (b.bit.three) ?'1':'0';
buf[4] = (b.bit.four) ?'1':'0';
buf[5] = (b.bit.five) ?'1':'0';
buf[6] = (b.bit.six) ?'1':'0';
buf[7] = (b.bit.seven) ?'1':'0';
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
isprint((int)c)?c:'.', c, c, c, buf);
}
return 0;
}
--
Yoshi
> Thanks for the suggestions, asides, I just come up with the following
> code that does not use loop, though not sure it's portable.
> typedef union _mychar{
You really don't like loops do you ... ?
Anyway you don't really need the union thing above:
buf[0]=(b & 0x80) ? '1' : '0';
buf[1]=(b & 0x40) ? '1' : '0';
...
And there are probably other ways of coding it.
BTW you should make buf a bit longer and set buf[8] to 0 (NUL), to make it a
proper string.
--
Bartc
Yes, a nice bit of lateral thinking there.
Although, once you accept using an array to do this, you are still going to
use either 1K or 4K of extra storage. With the string table being more
versatile (in being able to other things with the strings), and possibly a
little faster.
> I think a good compromise between table size and looping is to use
> unsigned shorts from 0 to 0x1111 and to print 4 bits at a time.
I think the OP has already decided to use shorts from 0 to 1, and print one
bit at a time...
--
Bartc
Bit fields of types other than int, signed int, unsigned int, and (C99
only) _Bool are not portable, though they're a common extension.
What does unsigned short buy you here vs. unsigned int?
Why are there 8 fields in the struct? Are you assuming CHAR_BIT==8?
You loop over the range 0..127, which only requires 7 bits.
> int main(void)
> {
> mychar b;
> unsigned int c;
> unsigned char buf[CHAR_BIT];
>
> for(c=0;c<=127;c++){
> b.c = c;
> buf[0] = (b.bit.zero) ?'1':'0';
> buf[1] = (b.bit.one ) ?'1':'0';
> buf[2] = (b.bit.two ) ?'1':'0';
> buf[3] = (b.bit.three) ?'1':'0';
> buf[4] = (b.bit.four) ?'1':'0';
> buf[5] = (b.bit.five) ?'1':'0';
> buf[6] = (b.bit.six) ?'1':'0';
> buf[7] = (b.bit.seven) ?'1':'0';
>
> printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
> isprint((int)c)?c:'.', c, c, c, buf);
> }
> return 0;
> }
How do you know whether bit.zero corresponds to the high-order bit of
c or the low-order bit? (Hint: You don't.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
>
> Anyway you don't really need the union thing above:
>
> buf[0]=(b & 0x80) ? '1' : '0';
> buf[1]=(b & 0x40) ? '1' : '0';
> ...
> And there are probably other ways of coding it.
>
> BTW you should make buf a bit longer and set buf[8] to 0 (NUL), to make it a
> proper string.
>
Yes, you're right, thanks.
--
Yoshi
> --
> Bartc
First I tried bool, but it didn't work(now I see it's _Bool). Then I
tried unsigned short, and it worked for gcc on Linux. I thought it
would be better since unsigned short would only consume 2 bytes, but
int would be 4 bytes(not good thing to do though..)
I usually try and error when I code, but could you tell me where
should I refer to write a portable code? I cannot see which standard
document I should check because it looks so many standards exist.
>
> Why are there 8 fields in the struct? Are you assuming CHAR_BIT==8?
> You loop over the range 0..127, which only requires 7 bits.
>
Yes, I was assuming 8 bits for char type, thank you.
>
>
> > int main(void)
> > {
> > mychar b;
> > unsigned int c;
> > unsigned char buf[CHAR_BIT];
>
> > for(c=0;c<=127;c++){
> > b.c = c;
> > buf[0] = (b.bit.zero) ?'1':'0';
> > buf[1] = (b.bit.one ) ?'1':'0';
> > buf[2] = (b.bit.two ) ?'1':'0';
> > buf[3] = (b.bit.three) ?'1':'0';
> > buf[4] = (b.bit.four) ?'1':'0';
> > buf[5] = (b.bit.five) ?'1':'0';
> > buf[6] = (b.bit.six) ?'1':'0';
> > buf[7] = (b.bit.seven) ?'1':'0';
>
> > printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
> > isprint((int)c)?c:'.', c, c, c, buf);
> > }
> > return 0;
> > }
>
> How do you know whether bit.zero corresponds to the high-order bit of
> c or the low-order bit? (Hint: You don't.)
>
OK, thanks for telling me that, though I want to see the reference...
Prior to C99, C didn't have a boolean type. A lot of code defined its
own type, often using the name "bool", so when the C99 committee
decided to add a boolean type, they couldn't make "bool" a keyword
without breaking existing code. So they introduced the keyword
"_Bool", but they also created the new <stdbool.h> header which
defines "bool" as an alias for "_Bool". (This doesn't break existing
code, since no existing code would have "#include <stdbool.h>".)
But note that both _Bool and bool are C99-specific, and some compilers
might not support it.
In any case, a bit field declared as
some_type bf:1;
will only occupy 1 bit, whatever some_type is. That's the whole
point.
If I wanted a 1-bit bit field, I'd use unsigned int:
unsigned int bf:1;
(A plain int bit field can be either signed or unsigned; that's an
annoyingly odd historical glitch in the language.)
> I usually try and error when I code, but could you tell me where
> should I refer to write a portable code? I cannot see which standard
> document I should check because it looks so many standards exist.
The current official standard for the C language consist of the 1999
ISO C standard plus the three Technical Corrigenda. They've been
conveniently merged into a not-quite-but-almost-official document,
<http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>.
Support for the C99 standard is not yet universal. The C90 standard
is still in wide use. I don't know of a good free source for it.
Note that the standard documents are quite dense; they're definitely
not tutorials. A good tutorial, arguably the best, is "The C
Programming Language", 2nd Edition, by Kernighan & Ritchie (K&R2). It
covers C90, not C99, but that's not much of a problem. A good
reference book is "C: A Reference Manual", 5th Edition, by Harbison &
Steele (H&S5). The comp.lang.c FAQ, <http://www.c-faq.com/>, is
another excellent resource; it also includes a section on other
resources, including some books that I've neglected to mention here.
[...]
>> How do you know whether bit.zero corresponds to the high-order bit of
>> c or the low-order bit? (Hint: You don't.)
>
> OK, thanks for telling me that, though I want to see the reference...
Any decent reference should explain how bit fields are defined. The
real point here, though, is the *lack* of any reference specifying how
bit fields are laid out (though you might find documents that describe
how they're handled by a particular compiler).
void bits(unsigned char b, int n) {
for (--n; n >= 0; --n)
putchar((b & 1 << n) ? '1' : '0');
putchar(' ');
}
--
Joe Wright
"If you rob Peter to pay Paul you can depend on the support of Paul."
very interesting story, then actually we would better not use _Bool
after all.
>
> In any case, a bit field declared as
>
> some_type bf:1;
>
> will only occupy 1 bit, whatever some_type is. That's the whole
> point.
Let me ask this point. since below code shows different size according
to each types(_Bool, unsigned short, unsigned int). so does it really
consume only 1 bit? I think I'm missing something..
It looks like each bit field consumes only 1 bit, but other bits are
not used in case of unsigned short and unsigned int.
#include <stdio.h>
typedef struct _mychar_b{
_Bool seven: 1;
_Bool six: 1;
_Bool five: 1;
_Bool four: 1;
_Bool three: 1;
_Bool two: 1;
_Bool one: 1;
_Bool zero: 1;
}mychar_b;
typedef struct _mychar_short{
unsigned short seven: 1;
unsigned short six: 1;
unsigned short five: 1;
unsigned short four: 1;
unsigned short three: 1;
unsigned short two: 1;
unsigned short one: 1;
unsigned short zero: 1;
}mychar_short;
typedef struct _mychar_int{
unsigned int seven: 1;
unsigned int six: 1;
unsigned int five: 1;
unsigned int four: 1;
unsigned int three: 1;
unsigned int two: 1;
unsigned int one: 1;
unsigned int zero: 1;
}mychar_int;
int main(void)
{
printf("sizeof mychar_b = %d\n",sizeof(mychar_b));
printf("sizeof mychar_short= %d\n",sizeof(mychar_short));
printf("sizeof mychar_int = %d\n",sizeof(mychar_int));
return 0;
}
Output is...
sizeof mychar_b = 1
sizeof mychar_short= 2
sizeof mychar_int = 4
>
> If I wanted a 1-bit bit field, I'd use unsigned int:
>
> unsigned int bf:1;
>
> (A plain int bit field can be either signed or unsigned; that's an
> annoyingly odd historical glitch in the language.)
>
> > I usually try and error when I code, but could you tell me where
> > should I refer to write a portable code? I cannot see which standard
> > document I should check because it looks so many standards exist.
>
> The current official standard for the C language consist of the 1999
> ISO C standard plus the three Technical Corrigenda. They've been
> conveniently merged into a not-quite-but-almost-official document,
> <http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>.
>
> Support for the C99 standard is not yet universal. The C90 standard
> is still in wide use. I don't know of a good free source for it.
>
> Note that the standard documents are quite dense; they're definitely
> not tutorials. A good tutorial, arguably the best, is "The C
> Programming Language", 2nd Edition, by Kernighan & Ritchie (K&R2). It
> covers C90, not C99, but that's not much of a problem. A good
> reference book is "C: A Reference Manual", 5th Edition, by Harbison &
> Steele (H&S5). The comp.lang.c FAQ, <http://www.c-faq.com/>, is
> another excellent resource; it also includes a section on other
> resources, including some books that I've neglected to mention here.
Thank you for valuable information, I'm being overwhelmed to find that
pdf file is over 550pages...but I think I should get H&S5 anyway.
>
> [...]
>
> >> How do you know whether bit.zero corresponds to the high-order bit of
> >> c or the low-order bit? (Hint: You don't.)
>
> > OK, thanks for telling me that, though I want to see the reference...
>
> Any decent reference should explain how bit fields are defined. The
> real point here, though, is the *lack* of any reference specifying how
> bit fields are laid out (though you might find documents that describe
> how they're handled by a particular compiler).
That's awesome, so I should not use bit fields for the case I need to
expect certain layout of bit fields. But how inconvenient!
Thank you, using putchar looks simpler and clearer.
It depends.
A lot of compilers do support much of C99, and support can be expected
to improve as time passes. If you want to use C99's boolean type,
it's probably best to use "#include <stdbool.h>" and refer to "bool"
rather than "_Bool".
You can even declare something very similar to C99's bool in C90:
typedef enum { false, true } bool;
It's not exactly equivalent in all cases, but it's close enough if
you're reasonably careful. You might try something like this:
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif
(Or you can just use 0, 1, and int, as C programmers have been
doing for years.)
Of course the FAQ discusses this; see section 9.
>> In any case, a bit field declared as
>>
>> some_type bf:1;
>>
>> will only occupy 1 bit, whatever some_type is. That's the whole
>> point.
>
> Let me ask this point. since below code shows different size according
> to each types(_Bool, unsigned short, unsigned int). so does it really
> consume only 1 bit? I think I'm missing something..
>
> It looks like each bit field consumes only 1 bit, but other bits are
> not used in case of unsigned short and unsigned int.
>
[code snipped]
>
> Output is...
>
> sizeof mychar_b = 1
> sizeof mychar_short= 2
> sizeof mychar_int = 4
Hmm. Yes, it appears that the type chosen for a bit field, at least
with some compilers, can affect the size of the structure as a whole.
This happens with gcc, and I've seen it before with other compilers (I
meant to mention that). I don't know why they do this. Perhaps the
alignment for the structure is based on the alignment of the
*declared* type of the bit field, even though it really shouldn't have
any effect.
The standard doesn't say anything about this; it's within the rather
wide range of permitted behavior, but I personally find it quite odd.
[...]
> That's awesome, so I should not use bit fields for the case I need to
> expect certain layout of bit fields. But how inconvenient!
Unless you're willing to depend on the behavior of a particular
compiler (which might change with the next version).
I:\c16>type pbin.c
#include <stdio.h>
int main(void) {
void prbin(unsigned int);
printf("0 = "); prbin(0); putchar('\n');
printf("1 = "); prbin(1); putchar('\n');
printf("15 = "); prbin(15); putchar('\n');
printf("16 = "); prbin(16); putchar('\n');
printf("255 = "); prbin(255); putchar('\n');
printf("256 = "); prbin(256); putchar('\n');
printf("1023 = "); prbin(1023); putchar('\n');
printf("1025 = "); prbin(1025); putchar('\n');
printf("43690 = "); prbin(43690); putchar('\n');
printf("65535 = "); prbin(65535); putchar('\n');
return 0;
}
void prbin(unsigned int i) {
int r;
r = i % 2;
if (i > 1)
prbin(i / 2);
putchar('0' + r);
return;
}
I:\c16>tcc pbin.c
Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
pbin.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland
International
Available memory 419134
I:\c16>pbin
0 = 0
1 = 1
15 = 1111
16 = 10000
255 = 11111111
256 = 100000000
1023 = 1111111111
1025 = 10000000001
43690 = 1010101010101010
65535 = 1111111111111111
I:\c16>
If you read right to left, Ben's suggestion comes out as: "byte" is a
constant that points to a character which is unsigned and constant.
If you're going to put "const" in (unsigned char *byte would do by
itself), then you might as well put as many as you can in.
>>> Could you explain why you used below?
>>> const unsigned char *const byte = s2;
>>
>> The second const is a promise that 'byte' will not be changed. The
>> code has the same effect without it but the const gives more
>> information.
>
> If you read right to left, Ben's suggestion comes out as: "byte" is a
> constant that points to a character which is unsigned and constant.
>
> If you're going to put "const" in (unsigned char *byte would do by
> itself), then you might as well put as many as you can in.
I had certain problems with pete's code (which is why I also posted a
version), but this was the main issue:
const unsigned char *const byte = s2;
How obfuscatory is that? 4 attributes to declare a simple pointer, or is it
5 -- or 6? Or perhaps 3. But why am I even wasting time counting?
At first there appears to be no type, until you spot 'char' in the middle.
Then it
looks like there is no variable defined (as my brain sees 'byte' as a type).
Then it's difficult to reconcile 'byte' with what this actually variable is,
a pointer to a char.
I think all const attributes should be banned, as they seem to contribute
nothing except making code look cluttered (and probably hiding the real
problems).
My version of that declaration would look something like:
char *p = s2;
(Or would do if there wasn't this business about sometimes chars having to
be unsigned. Which means either using unsigned char everywhere, or analysing
the code to see whether it will work with signed... but of course this is
trivial matter..)
--
Bartc
Then you would also either have to change the parameter list from
(char *s1, const void *s2, size_t n)
to something else, or use a cast.
> (Or would do if there wasn't this business about sometimes chars having
> to be unsigned. Which means either using unsigned char everywhere, or
> analysing the code to see whether it will work with signed... but of
> course this is trivial matter..)
--
pete
>>>Could you explain why you used below?
>>> const unsigned char *const byte = s2;
>>
>>The second const is a promise that 'byte' will not be changed.
> then you might as well put as many as you can in.
That was pretty much my thinking at the time.
--
pete
> int main(void)
> {
> unsigned char c = 0;
> char buf[sizeof c * CHAR_BIT + 1];
>
> do {
> bit_str(buf, &c, sizeof c);
> printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
> isprint(c) ? c : '.' , c, c, c, buf);
> } while (c++ != (unsigned)UCHAR_MAX);
> return 0;
> }
That cast doesn't do what I want.
I was trying to prevent c from promoting to type (signed int).
int main(void)
{
unsigned u = 0;
unsigned char c = 0;
char buf[sizeof c * CHAR_BIT + 1];
do {
bit_str(buf, &c, sizeof c);
printf("[%c] decimal:%03d octal:%03o hex:%02x bin:%s\n",
isprint(c) ? c : '.' , c, c, c, buf);
c += 1u;
} while (u++ != UCHAR_MAX);
return 0;
}
--
pete
Then, just for the record, s2 could also have been const though the
value of that is minimal.
--
Ben.
I'm still confused, then the second 'const' in the following line does
not mean anything?
const unsigned char const *byte;
--
Yoshi
It means exactly what the first one means. Having both of them is redundant.
--
Alan Curry
Yes, but that is typo. A few messages back pete wrote
const unsigned char *const byte;
Yoshi, have you read:
http://c-faq.com/decl/constptrconst.html
http://c-faq.com/decl/constparm.html
?
--
Ben.
voud printb(FILE *fp, unsigned char ch)
{
int i;
int mask = 1 << (CHAR_BIT -1);
for(i=0;i<CHAR_BIT;i++)
{
fputc(fp, (ch & mask) ? '1' : '0')
mask >>= 1;
/* for pathological platforms where sizeof int == 1 */
if( (mask & (1 << (CHAR_BIT - 1)) )
mask = 1 << (CHAR_BIT -2);
}
}
Once the fucntion is written it can be slotted in.
>>>>> const unsigned char *const byte = s2;
>>If you read right to left, Ben's suggestion comes out as: "byte" is a
>>constant that points to a character which is unsigned and constant.
>
>
> I'm still confused, then the second 'const' in the following line does
> not mean anything?
> const unsigned char const *byte;
const unsigned char *byte = s2;
means you can't do this:
*byte = 0;
unsigned char *const byte = s2;
means you can't do this:
++byte;
--
pete
It's too late to try to fix the problem here. The initial setting of
mask is undefined when 2**CHAR_BIT - 1 is not representable so there
is little value in trying to fix the problem of implementation-defined
signed left shifts.
The problem goes away if you make mask an unsigned int.
> }
> }
--
Ben.
The left operand of those shift operations,
should also be unsigned.
unsigned mask = 1u << (CHAR_BIT -1);
--
pete
Thank you, now I've got it.
--
Yoshi
>
> --
> Ben.
> Ben Bacarisse wrote:
>> "Malcolm McLean" <regn...@btinternet.com> writes:
<snip>
>>> int mask = 1 << (CHAR_BIT -1);
<snip fix for signed shift when sizeof(int) == 1>
>> The problem goes away if you make mask an unsigned int.
>
> The left operand of those shift operations,
> should also be unsigned.
>
> unsigned mask = 1u << (CHAR_BIT -1);
Yes. I took it as read that if you changed the type you'd use the
right type to initialise it, especially as the problem I was pointing
out was that 1 << (CHAR_BIT - 1) is undefined (in the specific case
that was being considered).
--
Ben.