memset、memmcpy、memmove実装とその違い

2684 ワード

この3つの関数は本当に古典的で、自分で実現しなければなりません.
3つの関数のプロトタイプは次のとおりです.
void* memset(void *des, int val, size_t size) 
void * memcpy(void *des, const void* src, size_t size)
void * memmove(void *des, const void *src, size_t size)

次のようになります.
void* memset(void *des, int val, size_t size) {
	void *start = des;
	while (size--) {
		*(char*) des = (char) val;
		des = (char *) des + 1;
//		(char*) des++;
		//		des = (char* )des + 1;
	}
	return start;
}
void * memcpy(void *des, const void* src, size_t size) {
	void *ret = des;
	while (size--) {
		*(char *) des = *(char *) src;
		des = (char *)des + 1;
		src = (char *)src + 1;
//		(char *) des++;
//		(char *) src++;
	}
	return ret;
}
void * memmove(void *des, const void *src, size_t size) {
	void *ret = des;
	if (des < src || (char *) des > (char *) src + size - 1) {
		while (size--) {
				*(char *) des = *(char *) src;
				des = (char *) des + 1;
				src = (char *)src + 1;
//				(char *) src++;
//				(chr *) des ++;
	}
	}else{
		des = (char *)des + size - 1;
		src = (char *)src + size - 1;
		while (size -- > 0){
			*(char *) des = *(char *) src;
//			(char *) des--;
//			(char *) src--;
			des = (char *)des - 1;
			src = (char *)src - 1;
		}
	}
	return ret;
}

//の表記を採用しないのは、パケットが警告を出すからです:warning:value computed is not used
不快に見える.
注意事項:
(1)memsetを使用する場合は、最下位または最下位の次の位置を「0」とする.
char buffer[20] = "hello";
memset(buffer, '1', sizeof(char)*20);
printf("%s
",buffer); :111111111111111111110@ char buffer[20] = "hello"; memset(buffer, '1', sizeof(char)*20); buffer[20] = '\0'; printf("%s
",buffer); :11111111111111111111

prinfの文字列が1つあるとき、printf関数は'0に出会って停止するからです.最初の例では、buffer[20]はすべて‘1’であり、終了には‘0’がないので、印刷された結果は不確定であると考えられる.もちろん、正しいかもしれませんが、それは運がいいだけです.
(2)memcpyとstrcpyの違い:
実際の違いは1つだけで、strcpyの操作オブジェクトはchar*しかなく、memcpyの操作オブジェクトはvoid*です.(どんなタイプでもOK).実際、memcpyの実装では、(void*)を(char*)に置き換えて作られていますが、実はstrcpyと同じです.
(3)memmoveとmemcpyの違い:
違いはmemmoveがメモリ区間が重なる場合を考慮し、memcpyはしません.
この問題については、以下の画像で説明できます.
メモリ区間が重複している場合は、メモリ区間が重複していない場合と次のようになります.
desがsrc+2であると仮定し、memcpy処理に従って最初からコピーを開始すると、次の悲劇が発生します.
srcのメモリは汚染されており、このとき*desの先頭のメモリを印刷すると、'0'が上書きされているため、定義されていない場合があります.
char buffer5[10] = "1234";
	memcpy(buffer5 + 2, buffer5, sizeof(buffer5));
	printf("%s
", buffer5); char buffer6[10] = "1234"; memmove(buffer6 + 2, buffer6, sizeof(buffer6)); printf("%s
",buffer6 + 2);
実行結果:
121212121212????"
1234