Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   memcmp() - compare buffer for 0 (http://www.velocityreviews.com/forums/t754748-memcmp-compare-buffer-for-0-a.html)

Mark 10-10-2011 09:38 PM

memcmp() - compare buffer for 0
 
Hello,

#define MAX_LEN 6
unsigned char buf[MAX_LEN];
unsigned char zerobuf[MAX_LEN] = { 0 };

if (memcmp(buf, zerobuf, MAX_LEN) == 0)
puts("buf is empty");
else
puts("buf is not empty");

Is there another way to compare the input buffer for being equal to some
pattern (all zeros in this case), i.e. ti avoid having additional array
zerobuf? I think memcmp(buf, "0", MAX_LEN) isn't valid.

Thanks.

Mark



Ike Naar 10-10-2011 11:18 PM

Re: memcmp() - compare buffer for 0
 
On 2011-10-10, Mark <mark_cruzNOTFORSPAM@hotmail.com> wrote:
> Hello,
>
> #define MAX_LEN 6
> unsigned char buf[MAX_LEN];
> unsigned char zerobuf[MAX_LEN] = { 0 };
>
> if (memcmp(buf, zerobuf, MAX_LEN) == 0)
> puts("buf is empty");
> else
> puts("buf is not empty");
>
> Is there another way to compare the input buffer for being equal to some
> pattern (all zeros in this case), i.e. ti avoid having additional array
> zerobuf? I think memcmp(buf, "0", MAX_LEN) isn't valid.


That's correct, memcmp(buf, "0", MAX_LEN) doesn't work.
One reason it won't work is that the character '0' is not the same
as a zero byte ('\0'). Another problem is that the array "0" has
less than MAX_LEN elements so there's the danger of reading beyond
the end of that array.

One other way to do it, that does not use an additional array,
is a simple linear search for the first nonzero element:

size_t i = 0;
while (i != MAX_LEN && buf[i] == 0) ++i;
if (i == MAX_LEN) puts("all zeroes"); else puts("not all zeroes");

Yet another way is to sort the buf array in descending order and
check whether buf[0] equals zero. If it does, the array contains
only zeroes.

There must be at least fifty other ways to do it.

Keith Thompson 10-11-2011 12:02 AM

Re: memcmp() - compare buffer for 0
 
"Mark" <mark_cruzNOTFORSPAM@hotmail.com> writes:
> #define MAX_LEN 6
> unsigned char buf[MAX_LEN];
> unsigned char zerobuf[MAX_LEN] = { 0 };
>
> if (memcmp(buf, zerobuf, MAX_LEN) == 0)
> puts("buf is empty");
> else
> puts("buf is not empty");
>
> Is there another way to compare the input buffer for being equal to some
> pattern (all zeros in this case), i.e. ti avoid having additional array
> zerobuf? I think memcmp(buf, "0", MAX_LEN) isn't valid.


If your compiler supports compound literals (a "new" feature in C99),
you can do something like this:

if (memcmp(buf, (char[MAX_LEN]){ 0 }, MAX_LEN) == 0)
puts("buf is empty");
else
puts("buf is not empty");

In the more general case -- well, it depends on just what the more
general case turns out to be. This may be a specific example of a
more general problem, but it's hard to tell what that more general
problem is.

(Note that an array is never really "empty". Your array is full; it
just happens to be full of zeros.)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Eric Sosman 10-11-2011 12:37 AM

Re: memcmp() - compare buffer for 0
 
On 10/10/2011 5:38 PM, Mark wrote:
> Hello,
>
> #define MAX_LEN 6
> unsigned char buf[MAX_LEN];
> unsigned char zerobuf[MAX_LEN] = { 0 };
>
> if (memcmp(buf, zerobuf, MAX_LEN) == 0)
> puts("buf is empty");
> else
> puts("buf is not empty");
>
> Is there another way to compare the input buffer for being equal to some
> pattern (all zeros in this case), i.e. ti avoid having additional array
> zerobuf? I think memcmp(buf, "0", MAX_LEN) isn't valid.


You think rightly, as others have explained.

To use memcmp(), you'll need to compare to a region of memory as
long as the test region, pre-initialized to the desired value. That's
inescapable: it's how memcmp() operates.

Alternatively, you could write a simple isAllZero() function that
just looped through the test region comparing each byte to the desired
value. That would surely use less data memory, but it's impossible to
tell without measurement whether it would be faster or slower.

The strspn() function might *almost* be made to work, if only you
weren't looking for zeroes. As things stand, I see no way to employ it.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Mark Adler 10-11-2011 04:35 AM

Re: memcmp() - compare buffer for 0
 
On 2011-10-10 14:38:59 -0700, Mark said:
> Is there another way to compare the input buffer for being equal to
> some pattern (all zeros in this case), i.e. ti avoid having additional
> array zerobuf?


I'm surprised that no one offered the obvious answer that uses memcmp()
without another array:

if (MAX_LEN > 0 && buf[0] == 0 && memcmp(buf, buf + 1, MAX_LEN - 1) == 0)
puts("buf is all zeros");
else
puts("buf has at least one non-zero value");

Though it's probably faster to compare each entry to zero, or even
faster to recast to an array of large integers and compare those to
zero.

Mark


Ian Collins 10-11-2011 04:37 AM

Re: memcmp() - compare buffer for 0
 
On 10/11/11 05:35 PM, Mark Adler wrote:
> On 2011-10-10 14:38:59 -0700, Mark said:
>> Is there another way to compare the input buffer for being equal to
>> some pattern (all zeros in this case), i.e. ti avoid having additional
>> array zerobuf?

>
> I'm surprised that no one offered the obvious answer that uses memcmp()
> without another array:
>
> if (MAX_LEN> 0&& buf[0] == 0&& memcmp(buf, buf + 1, MAX_LEN - 1) == 0)
> puts("buf is all zeros");
> else
> puts("buf has at least one non-zero value");
>
> Though it's probably faster to compare each entry to zero, or even
> faster to recast to an array of large integers and compare those to
> zero.


Usual alignment caveats apply!

--
Ian Collins

Ben Bacarisse 10-11-2011 09:00 AM

Re: memcmp() - compare buffer for 0
 
Eric Sosman <esosman@ieee-dot-org.invalid> writes:

> On 10/10/2011 5:38 PM, Mark wrote:
>> Hello,
>>
>> #define MAX_LEN 6
>> unsigned char buf[MAX_LEN];
>> unsigned char zerobuf[MAX_LEN] = { 0 };
>>
>> if (memcmp(buf, zerobuf, MAX_LEN) == 0)
>> puts("buf is empty");
>> else
>> puts("buf is not empty");
>>
>> Is there another way to compare the input buffer for being equal to some
>> pattern (all zeros in this case), i.e. ti avoid having additional array
>> zerobuf? I think memcmp(buf, "0", MAX_LEN) isn't valid.

>
> You think rightly, as others have explained.
>
> To use memcmp(), you'll need to compare to a region of memory as
> long as the test region, pre-initialized to the desired value. That's
> inescapable: it's how memcmp() operates.


There's a memcmp method that does not quite fit that description, though
it is not likely to useful.

In the same way that an object can be copied by successively doubling
the copy region, so a region can be compared for all bytes the same by
doubling the compare region (and it can be altered to handle longer
patterns than all-bytes the same)

assert(BUF_SZ != 0);
size_t clen = 1;
while (2*clen < BUF_SZ)
if (memcmp(buf, buf + clen, clen) == 0)
clen *= 2;
else return false;
return memcmp(buf, buf + clen, BUF_SZ - clen) == 0 && buf[0] == target;

Rather like the previous suggestion to change a O(n) algorithm (a
simple loop) into a O(n log(n)) one (sort and test buf[0]), this is no
more than an exercise in possibilities.

--
Ben.

Ben Bacarisse 10-11-2011 09:11 AM

Re: memcmp() - compare buffer for 0
 
Ian Collins <ian-news@hotmail.com> writes:

> On 10/11/11 05:35 PM, Mark Adler wrote:
>> On 2011-10-10 14:38:59 -0700, Mark said:
>>> Is there another way to compare the input buffer for being equal to
>>> some pattern (all zeros in this case), i.e. ti avoid having additional
>>> array zerobuf?

>>
>> I'm surprised that no one offered the obvious answer that uses memcmp()
>> without another array:
>>
>> if (MAX_LEN> 0&& buf[0] == 0&& memcmp(buf, buf + 1, MAX_LEN - 1) == 0)
>> puts("buf is all zeros");
>> else
>> puts("buf has at least one non-zero value");
>>
>> Though it's probably faster to compare each entry to zero, or even
>> faster to recast to an array of large integers and compare those to
>> zero.

>
> Usual alignment caveats apply!


Are there any in this case?

--
Ben.

Ian Collins 10-11-2011 09:15 AM

Re: memcmp() - compare buffer for 0
 
On 10/11/11 10:11 PM, Ben Bacarisse wrote:
> Ian Collins<ian-news@hotmail.com> writes:
>
>> On 10/11/11 05:35 PM, Mark Adler wrote:
>>> On 2011-10-10 14:38:59 -0700, Mark said:
>>>> Is there another way to compare the input buffer for being equal to
>>>> some pattern (all zeros in this case), i.e. ti avoid having additional
>>>> array zerobuf?
>>>
>>> I'm surprised that no one offered the obvious answer that uses memcmp()
>>> without another array:
>>>
>>> if (MAX_LEN> 0&& buf[0] == 0&& memcmp(buf, buf + 1, MAX_LEN - 1) == 0)
>>> puts("buf is all zeros");
>>> else
>>> puts("buf has at least one non-zero value");
>>>
>>> Though it's probably faster to compare each entry to zero, or even
>>> faster to recast to an array of large integers and compare those to
>>> zero.

>>
>> Usual alignment caveats apply!

>
> Are there any in this case?


What if the buffer is at an odd address?

--
Ian Collins

Ben Bacarisse 10-11-2011 09:22 AM

Re: memcmp() - compare buffer for 0
 
Ian Collins <ian-news@hotmail.com> writes:

> On 10/11/11 10:11 PM, Ben Bacarisse wrote:
>> Ian Collins<ian-news@hotmail.com> writes:
>>
>>> On 10/11/11 05:35 PM, Mark Adler wrote:
>>>> On 2011-10-10 14:38:59 -0700, Mark said:
>>>>> Is there another way to compare the input buffer for being equal to
>>>>> some pattern (all zeros in this case), i.e. ti avoid having additional
>>>>> array zerobuf?
>>>>
>>>> I'm surprised that no one offered the obvious answer that uses memcmp()
>>>> without another array:
>>>>
>>>> if (MAX_LEN> 0&& buf[0] == 0&& memcmp(buf, buf + 1, MAX_LEN - 1) == 0)
>>>> puts("buf is all zeros");
>>>> else
>>>> puts("buf has at least one non-zero value");
>>>>
>>>> Though it's probably faster to compare each entry to zero, or even
>>>> faster to recast to an array of large integers and compare those to
>>>> zero.
>>>
>>> Usual alignment caveats apply!

>>
>> Are there any in this case?

>
> What if the buffer is at an odd address?


Yes, I missed the last sentence right up to the point I hit send! Then
I what what was being proposed (and you were commenting on).

--
Ben.


All times are GMT. The time now is 04:13 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.