1. 程式人生 > >透徹分析C/C++中memset函式

透徹分析C/C++中memset函式

在C語言中,經常需要對記憶體進行操作,裡面涉及很多函式,但是memset函式的使用有一點需要大家格外注意,這也是我在做專案時遇到過的一個問題,除錯了很久才找出來錯誤。

函式原型是:void *memset(void *s, int ch, size_t n);
   函式功能是:將s所指向的某一塊記憶體中的前n個位元組的內容全部設定為ch指定的ASCII值, 第一個值為指定的記憶體地址,塊的大小由第三個引數指定,這個函式通常為新申請的記憶體做初始化工作, 其返回值為指向s的指標,它是對較大的結構體或陣列進行清零操作的一種最快方法。
   標頭檔案是:<memory.h>或<string.h>
    這些解釋在百度裡面隨處可見,而這裡需要強調的是一些需要引起大家重視的關鍵點。
    1. 基本應用場合
    memset函式通常用來對一塊已經分配地址的記憶體進行初始化,並且通常初始化為0或者字元'\0'(實際上是一樣的)。下面是一些常見例子。

/*===注意:這些例子如果同時執行需要在C++編譯環境下===*/
int i = 0;
// 例1:對字元陣列進行初始化
char buf[10];
memset(buf, '\0', sizeof(char) * 10);	// 0或者'\0'是等價的
for (i = 0; i < 10; ++i)
{
	printf("%c", buf[i]);
}
printf("\n");

// 例2:對字元指標所指區域初始化,必須已經分配記憶體
char* pBuf = (char *)malloc(sizeof(char) * 10);

if (pBuf != NULL)
{
	memset(pBuf, 0, sizeof(char) * 10);		// 0或者'\0'是等價的
	for (i = 0; i < 10; ++i)
	{
		printf("%c", pBuf[i]);
	}
	printf("\n");

	free(pBuf);
	pBuf = NULL;
}

// 例3:對整型陣列進行初始化
int iBuf[10];
memset(iBuf, 0, sizeof(int) * 10);
for (i = 0; i < 10; ++i)
{
	printf("%d ", iBuf[i]);
}
printf("\n");
上面的這些例子已經比較清楚地展示了memset函式的使用,當然,很常見的還有對結構體進行這樣的初始化操作,唯一的區別就是sizeof()的物件變成結構體即可,這裡大家可以自己嘗試。
    2. 需要注意的幾點
(1)memset中的第三個引數一定要使用sizeof操作符,因為每個系統下對型別長度的定義可能不一樣。
(2)memset中的第一個引數一定要是一個已知的、已經被分配記憶體的地址,否則會出錯。
(3)大家可能比較疑惑,memset的第一個引數已經有了被初始化空間的首地址,為什麼還要返回一個void*的指標去指向這個地址呢?這種結構在很多函式庫裡面比較常見,比如字串操作函式等,都有類似的現象,這裡之所以還要返回這個指標是為了實現鏈式程式設計,所謂鏈式程式設計,舉個例子大家就明白了。
// 例4:鏈式程式設計
int i = 0;
char cBuf [10];
char cBuf1[10];

// 這裡是關鍵!!!
memcpy(cBuf1, memset(cBuf, 'a', sizeof(char) * 10), sizeof(char) * 10);

for (i = 0; i < 10; ++i)
{
	printf("%c", cBuf[i]);
}
printf("\n");

for (i = 0; i < 10; ++i)
{
	printf("%c", cBuf1[i]);
}
printf("\n");
從上面這個例子中就可以看出,在memcpy這個函式中,直接使用了memset的返回值,用其來拷貝cBuf1這個字元陣列,這樣就可以直接連起來寫,看起來十分方便。但是這個例子的應用形式卻很少,只是為了說明這個問題才這樣寫的,具體的鏈式程式設計應用場合大家可以再仔細研究下,但是鏈式程式設計也使得程式碼變得有些不直觀,所以要有所取捨。
(4)最後一點,也是最重要的一點。一定要注意,memset是按照位元組對待初始化空間進行初始化的,也就是說,函式裡面的第二個引數的那個初值(一般為0)是按照一個一個位元組往第一個引數所指區域賦值的,所以,對於單位元組資料型別(char)可以初始化為任意支援的值,都沒有問題,但是對於非多位元組資料型別只能初始化為0,而不能初始化成別的初值,因為對所有位元組按任意順序賦值0的結果都是0,而如果初始化為其他的值,就會一個位元組一個位元組的進行賦值,從而出現奇怪的結果。比如說,上面的例3之所以沒有出錯就是因為初始化為0,但是如果初始化為1,那麼因為int一般是4個位元組,那麼相當於將一個int元素初始化成了0000 0001 0000 0001 0000 0001 0000 0001,這樣對於一個int元素肯定不是1,而是一個很大的數,結果出乎意料,所以一定要記住這一點,非常重要!!!

相關推薦

透徹分析C/C++memset函式(轉載只為查閱方便,若有侵權立刪)

透徹分析C/C++中memset函式       在C語言中,經常需要對記憶體進行操作,裡面涉及很多函式,但是memset函式的使用有一點需要大家格外注意,這也是我在做專案時遇到過的一個問題,除錯了很久才找出來錯誤。     &nbs

透徹分析C/C++memset函式

在C語言中,經常需要對記憶體進行操作,裡面涉及很多函式,但是memset函式的使用有一點需要大家格外注意,這也是我在做專案時遇到過的一個問題,除錯了很久才找出來錯誤。 函式原型是:void *memset(void *s, int ch, size_t n);    函式功

C++ 類成員函式分析

概述之前對成員變數的分佈進行了整理,今天就對成員函式進行整理。 1、非靜態成員函式C++的設計準則之一就是:非靜態成員函式至少和一般的非成員函式的執行效率相同。 為了實現上衣準則,編譯器會對非靜態成員函式進行改進,先看下面的例子: float func(const Point3d* _this) { .

C++memset()函式

前段專案中發現一個問題,程式總是在某個dynamic_cast進行動態轉換時出異常,查了半天才發現問題原來是出在memset的使用上,雖然問題本身顯而易見,但當處於幾十萬行程式碼量級中時,就變得不太那麼容易定位了。 本文歸納了下使用memset幾個需要注意的地方,雖然內容很簡單,但也希望

C++memset函式的用法

//複習陣列的時候,第一次見到了memset,學之。 memset:char型初始化函式 標頭檔案:<string.h> 或 <memory.h> 函式原型:void *memset(void *s , int ch , size_t  n ) m

C++memset函式

轉載自  http://blog.sina.com.cn/s/blog_6f611c300101e59l.htmlvoid * memset (void * S, int value, size_t num);函式作用:將ptr所指向的某一塊記憶體中的每個位元組的內容全部設定

C#VS一個函式呼叫另一個函式的程式碼樣例

//主函式 說明:下面的函式是想求許可證的十六位編號,最後一位是許可編號的校驗碼,是以本體碼("JY" + xukbh)為基礎來計算 entities[0].XuKeZhengBianHao = "JY" + xukbh + xukebianhaojiaoyanma(xukbh);  

C++類建構函式

我們在定義一個類之後,在利用該類定義了一個物件後,往往需要對該物件中資料成員變數進行初始化。有時候我們會誤操作,忘記初始化或者重複初始化,這樣做都會造成程式的崩潰。C++給我們提供了一個很有用的方法,就是類的建構函式。 C++類的建構函式,和其它成員函式一樣,在類中定義。不過建構函式和其他成

Telerik UI for ASP.NET AJAX教程:C函式程式設計

【下載Telerik UI for ASP.NET AJAX最新版本】 在面向物件程式設計(OOP)中,我們習慣於使用物件集合或簡單資料型別。我們經常使用LINQ對這些集合進行排序和過濾,作為業務邏輯行為或資料轉換的一部分。雖然這些是我們經常執行的有用任務,但很容易忘記C#中的函式可以被視為資料

C++STL函式物件

前言   所謂函式物件,即 Function Object ,或者稱之為仿函式(functors)。顧名思義,就是像函式的一種物件,我們可以把函式物件看作是一個函式與物件的結合,一方面,它本質上是一個物件,但主要功能是使用其成員函式(主要是operator())在不同的容器和函式中傳

c語言輸出函式putc_putchar_puts-printf

//輸入輸出:英文是Input/Output 簡稱IO。 //putchar:將指定的數值對應的ASCII字元列印到螢幕上。 //putc:不但指定數值,而且還可以指定列印到哪裡去。 //stdout:是指定列印到螢幕上 standard out . //putc可以指定列印到一個檔案(FILE *

c++ STLsort函式的三種使用方法

複習一下~ STL,C++中的標準模板庫, 使用起來方便並且效率較高; sort函式有三種用法: 一:對基本型別陣列從小到大排序 sort( 陣列名+n1,陣列名+n2); 將陣列中下標從n1到n2的元素進行從小到大排序,不包括n2,通過n1,n2 可以對整

c語言常用函式

memset void *memset(void *s, int ch, size_t n); 函式解釋:將s中當前位置後面的n個位元組 (typedef unsigned int size_t )

C語言函式自帶的排序函式qsort

之前一直不知道C語言還有預設的排序函式,而且還是快速排序的函式,當時覺得自己C語言白學了,瞭解之後我覺得應該把這個函式的用法和用例展示出來,供大家參考。 #include <stdlib.h> void qsort( void *buf, size_t num,

C語言的memset()函式的使用

函式名: memset功  能: 設定s中的所有位元組為ch, s陣列的大小由n給定用  法: void *memset(void *s, char ch, unsigned n);程式例:#include <string.h>#include <stdio.h>#include &l

C語言排序函式的用法

C語言中沒有預置的sort函式。如果在C語言中,遇到有呼叫sort函式,就是自定義的一個函式,功能一般用於排序。 一、可以編寫自己的sort函式。 如下函式為將整型陣列從小到大排序。 void sort(int *a, int l)//a為陣列地址,l為陣列長度

C語言函式指標

Q:函式指標是什麼意思? A:例如一個指標指向int變數,那麼這個指標就是儲存這個int變數在記憶體中儲存的地址。同理,函式指標就是指向一個函式的指標,那麼這個指標就是儲存這個函式在記憶體中儲存的起始

C++類函式過載

    在前邊的學習中,我們知道C++中支援函式的過載,並且知道函式過載有一下幾個特性:         -函式過載的本質是相互獨立的不同函式         -C++中通過函式名和函式引數確定函式呼叫         -無法直接通過函式名得到過載函式的入口地址      

C語言函式

在對C語言有過一定的瞭解之後,我們都會涉及到一個概念:函式。 那麼,什麼是函式呢? 首先,我們來看一段 程式碼: #include<stdio.h> int Max(int x,int y) { retutn (x>y)

C++繼承建構函式和解構函式的呼叫順序

class Fish:public Animal { public: Fish() { cout<<"this is Fish"<<endl; } ~Fish() { cout<<"this is free Fish"<<en