void
x_bzero(s, n)
void *s;
unsigned int n;
{
long long *ptr = (long long *) s;
unsigned int d;


n /= sizeof(long long);
d %= sizeof(long long);


while (n--) *ptr++ = 0;
}

Dear programmers, hi
I have a question about the function above. I'm calling that function from main with this x_bzero(str, 21); with str is an array of char with 21 elements in there (Last one is '\0') char str[21]

That function zeros out the buffer.

I don't want to use char instead of void on my function because I want it to be type less :) and before I was casting s to char which is one byte and I went to the loop and zero out each bye.

Now I know that the above way can be slow if I have a large array, and I tried to improve it by zeroing multiple bytes at the time (That is why I'm casting my buffer s to long long which is 8 bytes in 32bits).

My question is:
1. since long long is 8 bytes and I have 21 bytes, 21 / 8 == 2 which I go to while loop and zero out the 2 -> 8bytes, and I'll be let by 5bytes. I'm not zeroing out that 5 bytes but why my buffer is zero (nothing in there)?

  1. Is that even a good way to do it or there is better way?

  2. Since void is 1bytes and I have 21 of them, when I cast that buffer to long long I need to have 24 bytes (3 * 8) and I don't, does the compiler adds more bytes to it or does not use the left over bytes? (which in my case the left over is 5 bytes)

Thanks in Advance
Regards
Mark

Recommended Answers

All 11 Replies

your function is very nice, but i have to ask, what's wrong with

memset(string,0,21);

Hi
Thanks for ur reply

My question is i'm passing 21 bytes and long long is 8 bytes so 21 / 8 = 2 so i have 2 full 8 bytes. 21 % 8 = 5 which is the left over of the 21 bytes. now how computer deal with that? with rest of 5 bytes because its less than the 8 (long long) bytes.
Is it add bytes to it? or ignore the 5 bytes?

since I'm zeroing 2 -> 8 bytes and rest I'm not zeroing, why my buffer is all zero?

>since I'm zeroing 2 -> 8 bytes and rest I'm not zeroing, why my buffer is all zero?
It's not. It only zeroes out 8 bytes at a time. You probably assumed the entire string was zeroed when you tried to print it, since a 0 (or null character) indicates the end of a string.

As has already been mentioned, use memset instead of trying to implement an 'improved' version of a function from the standard library. Unless you've done profiling and determined that clearing out memory is actually slowing down your program, optimizations like this are just going to make your intentions less clear later on.

Just to show you how much performance you didn't gain by trying to optimize, I benchmarked your x_bzero() function against memset, each clearing out 100 kilobytes of data. memset is more than 10 times faster than your function. Seriously, don't reimplement standard library functions unless you actually know what you're doing.

well.... maybe it's a pedantic exercise assigned by his professor?

>well.... maybe it's a pedantic exercise assigned by his professor?
If that were the case, performance wouldn't be an issue in the first place.

Thank you all for your reply

jephthah is not a assignment since I just graduated

John A, Thank you so much for ur great help.
I'll use a memset from library. :)

I just have last question:
Since void is 1 byte and long long is 8 bytes and our total bytes are 21:
21 / 8 = 2 which is 2 block of 8 bytes
21 % 8 = 5 which is the left over bytes

So now when i'm casting buffer void *s to long long, what would happen to that 5 bytes, does computer adds 3 bytes to it to make full 8 bytes or just ignores it and uses only that first 16 bytes

Again thank u all for ur great help

Mark

>So now when i'm casting buffer void *s to long long, what would happen to that 5 bytes
Nothing. In 32 bit software, pointers are always 4 bytes. When you're casting pointer types, the compiler doesn't care if it's void* or char* or long long* or some_struct*; they're all 4 byte memory addresses. Types are simply there so that when you dereference the address contained in the pointer, the program knows what kind of data it's trying to deal with (in this case long long, or 8 bytes).

So basically my function makes the original buffer bigger. let say char s[21]:
sizeof(s) 4 bytes which pointing on 1byte

now my function:
long long m[21] which sizeof(m) is 4 bytes which now pointing to 8 bytes.

am I correct?

So how can I do multi byte zeroing, since in bzero source they said it would me much faster? (That was the whole purpose of that func to make me understand multi byte zeroing)

Thanks
Mark

>am I correct?
Let's put it this way. Forget the pointers, below is a decimal representation of some memory, each value is one byte (so each value can hold 256 different values, in this case 0-255). 005 128 240 177 054 011 140 134 223 198 099 123 Now let's say you have a char* named 'mystring' pointing to the start of this memory. If you assign mystring[0]=0 or *mystring=0 , here's how your memory will look: 000 128 240 177 054 011 140 134 223 198 099 123 Likewise if you assign mystring[1]=0 , your memory will look like: 005 000 240 177 054 011 140 134 223 198 099 123 Finally, you could also have a long long* named 'mylonglong' pointing to the start of this memory. If you assign mylonglong[0] = 0 , your memory will look like the following: 000 000 000 000 000 000 000 000 223 198 099 123 So to answer your question, yes, you are doing multibyte zeroing. And yes, you're correct that it's significantly faster than zeroing out each byte at a time. But memset normally does multibyte zeroing far more efficiently than a C function could ever do. That's because in most implementations of the standard library, assembly is inlined into the code to maximize efficiency.

commented: nice explanation. +5

Thanks you so much. You cleared everything. :)
I really appreciate all your help.


Thanks
Mark

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.