Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   memset (http://www.velocityreviews.com/forums/t587485-memset.html)

Gaijinco 01-26-2008 09:02 PM

memset
 
I'm having a headache using memset()

Given:

int v[1000000];
memset((void*)v, 1, sizeof(v));

Can I be 100% positive than v[i] = 1 for i > 0, or there is something
else I have to do?.

In various computers that I have tried it seems that the only value I
can copy to a range with memset() that works is 0.

Thanks.

Martin Vuille 01-26-2008 09:24 PM

Re: memset
 
Gaijinco <gaijinco@gmail.com> wrote in
news:a1148788-04c6-4a1b-8abe-ba7ffac20c95@c23g2000hsa.googlegrou
ps.com:

> I'm having a headache using memset()
>
> Given:
>
> int v[1000000];
> memset((void*)v, 1, sizeof(v));
>
> Can I be 100% positive than v[i] = 1 for i > 0, or there is
> something else I have to do?.
>
> In various computers that I have tried it seems that the only
> value I can copy to a range with memset() that works is 0.
>
> Thanks.
>


What you are trying to do will only work if sizeof( int ) == 1 in
your environment.

memset() manipulates bytes. If sizeof( int ) == 4 in your
environment, then each element of v will be set to 0x01010101.

MV

--
I do not want replies; please follow-up to the group.

Martin Ambuhl 01-26-2008 09:28 PM

Re: memset
 
Gaijinco wrote:
> I'm having a headache using memset()
>
> Given:
>
> int v[1000000];


You have no guarantee that v can be that large.

> memset((void*)v, 1, sizeof(v));


The cast to (void *) is just typing practice. Lose it.
>
> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
> else I have to do?.


Unless sizeof(int) == 1, you can be 100% positive that v[i] != 1.
Each of the sizeof(v) bytes, interpreted as unsigned chars, will have 1
stored in it. That means, on a binary machine, that each of the v[i]
will have sizeof(int) bits set. With the exception for sizeof(int) == 1,
that value cannot be 1.

> In various computers that I have tried it seems that the only value I
> can copy to a range with memset() that works is 0.


You are completely wrong. Note the recurring patterns in the output
from the following program:
#include <stdio.h>
#include <string.h>

int main(void)
{
unsigned int v;
unsigned int i;

printf("Output on an implementation with sizeof(int) = %zu\n\n",
sizeof(int));

for (i = 0; i < 17; i++) {
printf("Setting each byte in the unsigned int v to %#x:\n", i);
memset(&v, i, sizeof v);
printf(" %#0x\n", v);
}
return 0;
}


Output on an implementation with sizeof(int) = 4

Setting each byte in the unsigned int v to 0:
0
Setting each byte in the unsigned int v to 0x1:
0x1010101
Setting each byte in the unsigned int v to 0x2:
0x2020202
Setting each byte in the unsigned int v to 0x3:
0x3030303
Setting each byte in the unsigned int v to 0x4:
0x4040404
Setting each byte in the unsigned int v to 0x5:
0x5050505
Setting each byte in the unsigned int v to 0x6:
0x6060606
Setting each byte in the unsigned int v to 0x7:
0x7070707
Setting each byte in the unsigned int v to 0x8:
0x8080808
Setting each byte in the unsigned int v to 0x9:
0x9090909
Setting each byte in the unsigned int v to 0xa:
0xa0a0a0a
Setting each byte in the unsigned int v to 0xb:
0xb0b0b0b
Setting each byte in the unsigned int v to 0xc:
0xc0c0c0c
Setting each byte in the unsigned int v to 0xd:
0xd0d0d0d
Setting each byte in the unsigned int v to 0xe:
0xe0e0e0e
Setting each byte in the unsigned int v to 0xf:
0xf0f0f0f
Setting each byte in the unsigned int v to 0x10:
0x10101010



Jack Klein 01-26-2008 09:31 PM

Re: memset
 
On Sat, 26 Jan 2008 13:02:39 -0800 (PST), Gaijinco
<gaijinco@gmail.com> wrote in comp.lang.c:

> I'm having a headache using memset()
>
> Given:
>
> int v[1000000];
> memset((void*)v, 1, sizeof(v));


No need for the cast to void pointer here, the conversion is
automatic. But do make sure to include <string.h>. Also there is no
need for the parentheses abound the 'v' as an operand to the sizeof
operator, as 'v' is an object, not a type.

> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
> else I have to do?.


No you can't, and on most implementations it will not be. memset()
will place the value 1 into every byte that makes up the array, and
there are 1,000,000 times sizeof (int) bytes in the array.

There are a few implementations, mostly digital signal processors,
where CHAR_BIT is 16 and char and int have the same size and
representation, where every int in the array will be set to the value
1.

But on most platforms, especially anything in a desktop computer, you
won't get that value.

On old 16-bit implementations for MS-DOS, each int in the array will
wind up with the value 257.

On 32-bit Windows, Macintosh, or Linux platforms using x86 processors,
each int in the array will have the value 16843009.

On 64-bit operating systems using x86, the result will be
72340172838076673.

> In various computers that I have tried it seems that the only value I
> can copy to a range with memset() that works is 0.


It works for a value of 0 because memset() with a value of 0 will set
every bit in every byte to all bits 0. C guarantees that any integer
type with a value of all bits 0 has the value 0. This is not
guaranteed for floating point types or pointers.

As to how to do it, you need to use a loop:

#define ARRAY_SIZE 1000000

int v [ARRAY_SIZE];

size_t index;

for (index = 0; index < ARRAY_SIZE]; ++index)
{
v [index] = 1;
}

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html

William Ahern 01-26-2008 09:38 PM

Re: memset
 
Gaijinco <gaijinco@gmail.com> wrote:
> I'm having a headache using memset()


> Given:


> int v[1000000];
> memset((void*)v, 1, sizeof(v));


> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
> else I have to do?.


> In various computers that I have tried it seems that the only value I
> can copy to a range with memset() that works is 0.


Mental exercise:

What's the difference, and expected result, of

char v[1000000];
memset(v, 1, sizeof v);

Hint: How does memset() know the stride when setting each element in the
array? Particularly given that in your example you explicitly cast the array
to a void pointer. Do you believe that memset() actually possesses this sort
of magic? It certainly _could_, cast or not, notwithstanding the correct
answer.

The precise answer is much more involved, of course.

Keith Thompson 01-26-2008 10:03 PM

Re: memset
 
Gaijinco <gaijinco@gmail.com> writes:
> I'm having a headache using memset()
>
> Given:
>
> int v[1000000];
> memset((void*)v, 1, sizeof(v));
>
> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
> else I have to do?.


No, you can be 99% positive that v[i] != 1 for i > 0. (The remaining
1% is for systems with sizeof(int)==1, and therefore CHAR_BIT>=16;
you're unlikely to run into such a system unless you're working with
embedded DSPs.)

> In various computers that I have tried it seems that the only value I
> can copy to a range with memset() that works is 0.


Right. memset sets each *byte* of an object to a specified value. It
happens that setting each byte of an int to 0 sets the entire int to
0. Setting each byte of an int to 1 will probably set the entire int
to something like 0x0101 (257), or 0x01010101 (16843009), or even
0x0101010101010101 (72340172838076673, if I've done the math right).

The C standard library doesn't provide functions to set each element
of an array to a specified value, other than memset. You'll just have
to write a loop (untested code follows):

int v[1000000];
size_t i;
for (i = 0; i < sizeof v / sizeof v[0]; i ++) {
v[i] = 1;
}

It's likely to be about as fast as memset() would have been anyway.

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

Eric Sosman 01-26-2008 10:21 PM

Re: memset
 
Keith Thompson wrote:
> Gaijinco <gaijinco@gmail.com> writes:
>> I'm having a headache using memset()
>>
>> Given:
>>
>> int v[1000000];
>> memset((void*)v, 1, sizeof(v));
>>
>> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
>> else I have to do?.

>
> No, you can be 99% positive that v[i] != 1 for i > 0. (The remaining
> 1% is for systems with sizeof(int)==1, and therefore CHAR_BIT>=16;
> you're unlikely to run into such a system unless you're working with
> embedded DSPs.)
>
>> In various computers that I have tried it seems that the only value I
>> can copy to a range with memset() that works is 0.

>
> Right. memset sets each *byte* of an object to a specified value. It
> happens that setting each byte of an int to 0 sets the entire int to
> 0. Setting each byte of an int to 1 will probably set the entire int
> to something like 0x0101 (257), or 0x01010101 (16843009), or even
> 0x0101010101010101 (72340172838076673, if I've done the math right).
>
> The C standard library doesn't provide functions to set each element
> of an array to a specified value, other than memset. You'll just have
> to write a loop (untested code follows):
>
> int v[1000000];
> size_t i;
> for (i = 0; i < sizeof v / sizeof v[0]; i ++) {
> v[i] = 1;
> }
>
> It's likely to be about as fast as memset() would have been anyway.


For very large arrays that need to be filled/refilled very
many times, here's a function I cooked up long ago:

#include <string.h>
void fillmem(void *pdest, size_t sdest,
const void *pfrom, size_t sfrom)
/*
* Fills the `sdest' bytes starting at `pdest' with copies
* of the `sfrom' bytes starting at `pfrom'. The final copy
* will be partial if `sfrom' does not divide `sdest'.
*/
{
if (sdest > sfrom) {
memcpy (pdest, pfrom, sfrom);
pfrom = pdest;
pdest = (char*)pdest + sfrom;
sdest -= sfrom;

while (sdest > sfrom) {
memcpy (pdest, pfrom, sfrom);
pdest = (char*)pdest + sfrom;
sdest -= sfrom;
sfrom += sfrom;
}
}

memcpy (pdest, pfrom, sdest);
}

<off-topic> At first glance and even at second glance, this looks
like a cache-killer. But on the platforms I've tested it doesn't
appear to suffer from cache-aliasing problems. It seems likely
that memcpy() on these platforms is implemented cleverly (and non-
portably) to dodge such issues. </off-topic>

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

Pedro Graca 01-26-2008 10:29 PM

Re: memset
 
Gaijinco wrote:
> I'm having a headache using memset()


int v[100];
memset(v, 1, sizeof v);

How many times are you copying the 1?
It is not 100 times!

----------------
#include <stdio.h>
int main(void) {
int v[100];
/* sorry about the cast: my compiler doesn't like %zu */
printf("sizeof v is %lu.\n", (unsigned long)sizeof v);
return 0;
}
----------------

If you copy 400 values of 1 into v, you cannot expect each of the
values to be 1 :)

Army1987 01-27-2008 01:30 PM

Re: memset
 
Martin Ambuhl wrote:

>> memset((void*)v, 1, sizeof(v));


>> Can I be 100% positive than v[i] = 1 for i > 0, or there is something
>> else I have to do?.

>
> Unless sizeof(int) == 1, you can be 100% positive that v[i] != 1.

Let's say 99.99999999%, since it is possible that the least significant bit
of each byte except one of them is a padding bit.


--
Army1987 (Replace "NOSPAM" with "email")

dj3vande@csclub.uwaterloo.ca.invalid 01-28-2008 09:09 PM

Re: memset
 
In article <QKOdnRBFGboHLwbanZ2dnUVZ_ournZ2d@comcast.com>,
Eric Sosman <esosman@ieee-dot-org.invalid> wrote:

> For very large arrays that need to be filled/refilled very
>many times, here's a function I cooked up long ago:
>
> #include <string.h>
> void fillmem(void *pdest, size_t sdest,
> const void *pfrom, size_t sfrom)
> /*
> * Fills the `sdest' bytes starting at `pdest' with copies
> * of the `sfrom' bytes starting at `pfrom'. The final copy
> * will be partial if `sfrom' does not divide `sdest'.
> */
> {
> if (sdest > sfrom) {
> memcpy (pdest, pfrom, sfrom);
> pfrom = pdest;
> pdest = (char*)pdest + sfrom;
> sdest -= sfrom;
>
> while (sdest > sfrom) {
> memcpy (pdest, pfrom, sfrom);
> pdest = (char*)pdest + sfrom;
> sdest -= sfrom;
> sfrom += sfrom;
> }
> }
>
> memcpy (pdest, pfrom, sdest);
> }
>
><off-topic> At first glance and even at second glance, this looks
>like a cache-killer. But on the platforms I've tested it doesn't
>appear to suffer from cache-aliasing problems. It seems likely
>that memcpy() on these platforms is implemented cleverly (and non-
>portably) to dodge such issues. </off-topic>


How 'bout something like this?
--------
void fillmem(void *pdest,size_t sdest,const void *pfrom,size_t sfrom)
{
if(sdest <= sfrom)
{
memcpy(pdest,pfrom,sdest);
return;
}
/*Make the first copy of from*/
memcpy(pdest,pfrom,sfrom);
/*Now make the rest of the copies from the last copy
we made
*/
memmove((char *)pdest + sfrom,pdest,sdest-sfrom);
}
--------
I would expect this to be more cache-friendly[1], since after the
initial copy it's (in the abstract, at least) a simple linear walk
through memory for each of read and write, instead of walking through
the beginning of the array log2(N) times (going farther each time).
This takes advantage of the defined-on-overlap semantics of memmove; is
losing any optimizations memcpy can make that memmove can't a
sufficiently low price to pay for any benefits this approach might
have?

(Interestingly, I invented this independently about a week before
reading a description in comp.arch of the same technique being used in
a system older than I am.)


dave

[1] Keeping in mind that I know next to nothing about caching behavior
of modern processors

--
Dave Vandervies dj3vande at eskimo dot com
BTW, bottlenecks are Good: Unless I can find one or a few, speeding up a
procedure/algorithm/program is _much_ harder.
--Terje Mathisen in comp.arch


All times are GMT. The time now is 10:15 PM.

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