2012-03-22 273 views
0

我正在學習套接字編程,並且我遇到了這段代碼。關於memset的困惑

struct addrinfo hints, *res, *p; 
int status; 
char ipstr[INET6_ADDRSTRLEN]; 

if (argc != 2) { 
    fprintf(stderr,"usage: showip hostname\n"); 
    return 1; 
} 

memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version 
hints.ai_socktype = SOCK_STREAM; 

if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { 
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); 
    return 2; 
} 

我明白這一切,除了一個。爲什麼這個代碼memset了結構提示,但不是* res和* p?

+1

更好的風格是初始化'提示'而不是調用'memset'。 – 2012-03-22 10:42:15

回答

3

res指針將由getaddrinfo函數填充,因此不需要通過零初始化。另一方面需要初始化另一個hints,因此將整個結構設置爲零,然後設置僅需要設置的兩個字段。

由於您在代碼中不使用p - 我無法評論它。

0

它不應該只是你所有的0的memset提示。另外,res和p指針只在memset調用時沒有定位到任何位置。

這是預期的行爲。讓我知道你的例外,我將能夠更好地幫助你。

0

爲什麼這段代碼memset了結構提示,但不是* res和* p?

因爲,您只調用一次memset並僅將&提示作爲參數傳遞給該memset。

memset(&hints, 0, sizeof hints); 

如果你想memset的* RES & * P,首先你需要同他們onlypointers,然後你需要通過將其作爲參數seperately對於他們中的每一個調用memset的分配內存。

+0

所以我可以memset * res,但它沒有任何意義,因爲getaddrinfo會覆蓋它嗎? – 2012-03-22 15:30:26

+0

你不能memset'* res',因爲指針是無效的(包含「垃圾」,因爲它沒有被初始化 - 因此指向無效的「對象」)。你可以memset指針本身('res'),但是如果你想這樣做,分配零('res = 0;')也很容易。你說得對,函數調用會在它返回時爲'res'賦值。 - 澄清:'res'的類型是'struct addrinfo *'(指向addrinfo結構的指針),'* res'的類型是'struct addrinfo'(結構本身,而不是指針) – Attila 2012-03-23 20:32:09

1

getaddrinfo的說明指出

的的getaddrinfo()函數分配和初始化addrinfo中結構的一個鏈表,一個用於相匹配的節點和服務中的每個的網絡地址,受提示施加的任何限制,並返回一個指向res中列表開始的指針。

這意味着你不會在嚴格需要(否則該函數可能會產生不希望的輸出)hints中獲得任何其他信息。此外,該函數的「實際」結果返回res,這意味着res的當前內容被覆蓋,因此您不會在函數調用之前關心內存中的內容(只要您不打算解釋如果該功能失敗)。

由於結構的成員(如addrinfo)在聲明該類型的變量時沒有以任何方式初始化,所以hints最初包含「垃圾」 - 無論發生在分配變量的內存中。因此,代碼調用memset以簡單/快速的方式將所有成員清零(而不是逐個設置成員變量爲零)。