[英]create my own memset function in c
這是原型:
void *memset(void *s, int c, size_t n)
首先,我不確定我是否必須返回某些東西,因為當我使用記憶集時,例如
memset(str, 'a', 5);
代替
str = memset(str, 'a', 5);
這是我的代碼所在的位置:
void *my_memset(void *b, int c, int len)
{
int i;
i = 0;
while(b && len > 0)
{
b = c;
b++;
len--;
}
return(b);
}
int main()
{
char *str;
str = strdup("hello");
my_memset(str, 'a', 5);
printf("%s\n", str);
}
我不想在此函數中使用數組,以便更好地理解指針和內存,所以我沒有得到兩件事:-如何將int c復制到我的void b指針上的一個字符中-在我使用的同時要確保什么條件它在'\\ 0'字符之前停止
編輯:我想知道是否有一種無需鑄造就可以完成此功能的方法?
如何將int c復制到我的void b指針上的字符中
您將void指針轉換為無符號char指針:
void *my_memset(void *b, int c, int len)
{
int i;
unsigned char *p = b;
i = 0;
while(len > 0)
{
*p = c;
p++;
len--;
}
return(b);
}
我在使用什么條件來確保它在'\\ 0'字符之前停止
memset必須信任傳入的長度。memset需要在一般的內存上工作,而不僅僅是終止於0的字符串-因此不應進行此類檢查。
如果您仍然需要檢查0字節。 你會做
if (*p == 0) //or if(!*p )
break;
指針算術基於將指針偏移其指向的類型的大小。 在開始增加該指針之前,應將其從void*
轉換為char
/ unsigned char
指針:
void* my_memset(void *s, int c, size_t len) {
unsigned char *dst = s;
while (len > 0) {
*dst = (unsigned char) c;
dst++;
len--;
}
return s;
}
還要注意, memset
返回指向存儲區s的指針 ,因此您應該返回原始指針(在開始遞增它之前)。
函數通常返回值的原因是為了將錯誤狀態返回給調用函數。 在與內存相關的函數中,它通常與結果應包含的指針相同(包括NULL)。 在您的示例中,您可能不想使用my_memset
函數的返回值,但這通常是因為它可以包含在代碼評估中(為此想不到一個更好的詞),例如
if(!my_memset((void *)str, 'a', 5))
{
printf("An error occurred in my_memset()\n");
}
或在宏中,例如,返回指向復制char
的內存末尾的指針:
#define INIT_MEM_PTR_END(a,x) (my_memset((void *)&(a), (x), sizeof(a)) + sizeof(a))
這可能不是一個好例子(如果a
已經是指針等,還會加上潛在的問題,等等),但是它表明您可以重用結果,而不必為此寫另外幾行代碼來評估結果,因此上。
在取消引用指針之前,還應該檢查指針。 例如,如果void *b
為NULL,則將出現分段錯誤。
傳遞void *
沒什么不對,除了函數的意圖可能不如傳遞指向特定數據類型的指針時那樣明確。 確保將其投射到內部有效的東西上。 同樣,通過這種方式,該函數可以很容易地將任何內存設置為特定的十六進制值(通過char)或全0。
在這種情況下,似乎b
應該轉換為與您要復制到其中的值相同的類型,即int
; 但是, len
參數變得不清楚,是以字節為單位還是將c
復制到b
指針的次數?
由於在main()
中將一個char
復制到該內存位置,因此最好將c
更改為char
,將b
轉換為char*
然后將len
的長度以字節為單位或將c
設為復制到*b
。 避免歧義。
編寫方式將復制len
指定的c
次或直到遇到空字符(以最短/最快的時間為准)。 如果那是您的意圖,那很好。
void *my_memset(void *b, char c, int len)
{
char *b_char = (char *)b;
if (b == NULL) return NULL;
while(*b_char && len > 0)
{
*b_char = c;
b_char++;
len--;
}
return b; //as this pointer has not changed
}
int main()
{
char *str;
str = strdup("hello");
if (!my_memset((void *)str, 'a', 5))
{
printf("An error occurred in my_memset()\n");
}
else
{
printf("%s\n", str);
}
}
您可以使用Duff設備來獲得更好的性能。
#define DUFF_DEVICE_8(aCount, aAction) \
do { \
int count_ = (aCount); \
int times_ = (count_ + 7) >> 3; \
switch (count_ & 7){ \
case 0: do { aAction; \
case 7: aAction; \
case 6: aAction; \
case 5: aAction; \
case 4: aAction; \
case 3: aAction; \
case 2: aAction; \
case 1: aAction; \
} while (--times_ > 0); \
} \
} while (0)
void *my_memset(void *b, int c, int len)
{
if (b == NULL || len <= 0)
return b;
unsigned char *ptr = b;
while(*ptr != '\0' && len--)
{
*ptr++ = (unsigned char)c;
}
return(b);
}
我嘗試了這樣的一種實現:
void memset(void *b, int c, int len)
{
char *s = b;
while(len--)
*s++ = c;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.