tags:

views:

162

answers:

4

The prototype of memset is void *memset(void *s, int c, size_t n);. So why the third parameter is of type size_t ? memset is just an example, I want more general reasons. Thanks in advance.

+5  A: 

size_t is the return type of the sizeof operator and is used to describe memory sizes. In the case of memset, it specifies the number of bytes (n) in the memory block (s) that should be set to the given value (c).

The size in bits of size_t varies based on the address space of the target platform. It does not always correlate to the register size. For example, in a segmented memory architecture the sizeof (size_t) can be smaller than the sizeof (void *). Typically, size_t would be 4 bytes on a 32-bit machine, 8 bytes on a 64-bit machine, etc.

Judge Maygarden
Could you please explain more about why `sizeof (size_t) can be smaller than the sizeof (void *)`? Thanks a lot ;)
Grissiom
In segmented memory, the size of each segment is smaller than the total memory size. For example, in a 80286 you can address 2^24 total bytes but only only use 2^16 contiguous bytes within each segment. See http://en.wikipedia.org/wiki/Memory_segmentationNow, I don't have a 80286 with a C99 compiler on it handy, but I'd guess that sizeof (size_t) == 2 and sizeof (void *) == 4.
Judge Maygarden
So what it will be when I try to memset 2^20 bytes in 80286? Although it's too large but I think it make sense because we can address 2^24 bytes.
Grissiom
In that case you would overflow the `size_t` variable and not `memset` any bytes because `(1 << 20) % (1 << 16) == 0`.
Judge Maygarden
The reason that you can only `memset` 2^16 bytes instead of 2^20 or 2^24 is that the segment offset register has to be changed to go beyond 64 kB. Otherwise, the address would wrap around back to the beginning. To prevent this it makes sense to use a 16-bit `size_t` with a 32-bit `void *`. Note that C supports different pointer types to deal with segmented architectures ("near, far and huge":http://en.wikipedia.org/wiki/Intel_Memory_Model).
Judge Maygarden
As has been said in comments to other questions, you probably don't need to worry about segmented architectures anymore. On modern commodity PC hardware, `size_t` is big enough for all of main memory (i.e. RAM).
Judge Maygarden
I work at a very low level with a variety of different microcontrollers. So, I'm nit-picky about this stuff.
Judge Maygarden
Never mind, I work on embedded programming as well ;-) So, in the condition on 80286, does it mean that we can _address_ 2^24 byte RAM but we cannot use 0 to 2^24 byte as a whole? If one want to use large object like that, he has to divide them into 2^16 bytes segments?
Grissiom
@Grissiom Yes, that is correct.
Judge Maygarden
+2  A: 

size_t is the type used to denote the size of objects. In C sizes of integer types (int, long, etc.) are implementation-dependent and you need to use the right type on each compiler implementationp so that the size is big enough to store all possible values.

The headers that will come with the platform SDK will have a typedef that will map size_t to the right integer type. So you write memset() once and it compiles right on every implementation.

sharptooth
+1  A: 

size_t is a type suitable for representing the amount of memory a data object requires. It is an unsigned integer type (generally, typedef unsigned int size_t;).

Read this link for more information.

Yassin
That's not true. On many (if not most) 64-bit platforms `unsigned int` is 32-bit, while `size_t` is 64-bit.
slacker
Yes, you're right!
Yassin
A: 

size_t is guaranteed to be large enough to hold a pointer on all platforms.

jemfinch
See Judge Maygarden's answer.
user9876
Nice downmod, but if you actually read and understand Judge Maygarden's answer, you'll see that we're saying the exact same thing. "The size in bits of size_t varies based on the address space of the target platform" is isomorphic to "size_t is guaranteed to be large enough to hold a pointer on all platforms."Judge Maygarden said that size_t might be smaller than the register size on some platforms. He did not say it might be smaller than the pointer size, because it cannot be.
jemfinch
So what is the difference between register size and pointer size?
Grissiom
On many processors, nothing. On some processors, there are multiple registers of different sizes; on others, a general purpose register may be half the size of a pointer, and registers may need to be combined to load from memory. The point Judge Maygarden was making is that the relation is not between the size of a register and the size of `size_t`, but between memory size and the size of `size_t`: that is to say, that size_t is large enough to reference all of memory (just like...a pointer!).
jemfinch
Yup, life could be more easier if size_t is large enough to reference all of memory. But what does Judge Maygarden mean by "sizeof (size_t) can be smaller than the sizeof (void *)"? Doesn't (void *) is the largest pointer?
Grissiom
He has a good point, but that's not what he originally said: he added that point in an edit.He's right, though: size_t is only guaranteed to be able to access all the memory in a given bank of a segmented architecture. Programmers haven't had to worry about that for a very long time, though :)
jemfinch
It is even possible for there to be *no* integer type large enough to hold the largest pointer type. C99 defines (the optional) `intptr_t` and `uintptr_t` types that are large enough to hold any object pointer (i.e. not a function pointer) including `void *`. Meanwhile `size_t` only needs to be large enough to represent, as the name says, sizes. As an example, consider a segmented architecture where a “far” pointer may point to memory outside the current segment but the area of memory pointed to must fit inside a single segment; the pointer could be 32 bits with a 16-bit `size_t`.
Arkku
But what is the meaning of "sizes"? That word is too abstract. Does it mean the size of address bus or the size of registers?
Grissiom
The size described by `size_t` is the length in bytes of a contiguous block of memory.
Judge Maygarden
So I'm curious: are you guys just being pedantic, or are there *actual machines* in common use today for which "size_t is guaranteed to be large enough to hold a pointer" does not hold? I'm not aware of any; segmented memory architectures are a relic of the PDP days, as far as I know.
jemfinch
I believe real mode is still supported in IA-32 processors. So, this could happen with a compiler targeting the 8086 addressing mode. AMD64 deprecated the segment registers.However, yes, we are mostly being pedantic. That's why I didn't down vote your answer. Although it is technically incorrect per the C standard.
Judge Maygarden