2015-11-08 66 views
2
#include <sys/socket.h> 
#include <err.h> 
#include <stdio.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
int main(int argc, char **argv) { 

    struct sockaddr_in X = {0}; 
    X.sin_family = AF_INET; 
    X.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    X.sin_port = htons(8080); 

    struct sockaddr_in Y = {0}; 
    Y.sin_family = AF_INET; 
    Y.sin_addr.s_addr = inet_addr("212.43.159.20"); 
    Y.sin_port = htons(80); 

    printf("X:Y %s:%s\n", inet_ntoa(X.sin_addr), inet_ntoa(Y.sin_addr)); 
    printf("X %s\n", inet_ntoa(X.sin_addr)); 
    printf("Y %s\n", inet_ntoa(Y.sin_addr)); 

    return 0; 
} 

爲什麼第一個pritnf打印兩次相同的IP而不是給定的? 第二和第三似乎沒問題。 似乎發生在linux gcc/clang和freebsd clang上,這是已知的事情嗎?奇怪的printf行爲與inet_ntoa

回答

2

看一看的POSIX文檔爲inet_ntoa,著名的「應用程序使用情況」一節:

inet_ntoa()返回值可能指向可以通過後續調用inet_ntoa()被覆蓋的靜態數據。

這就是發生在這裏:在其中一個通話在你第一次printf被覆蓋什麼其他的了(而你不知道哪一個 - 函數參數的計算順序定義實現)。

因此,要麼堅持兩個printfs,要麼將inet_ntoa返回的字符串複製到您自己的緩衝區,然後打印它們。

+0

我傾向於通過使用'inet_ntop'來避免這個問題。 – jch

4

從手冊頁inet_ntoa

inet_ntoa()功能的互聯網主機地址中給出 網絡字節順序轉換到標準的數字 - 點 符號的字符串。 該字符串在靜態分配的緩衝區中返回, 後續調用將被覆蓋。

由於inet_ntoa使用靜態緩衝區輸出,因爲你在一個函數調用兩次調用它,printf被傳遞同一指針的兩個副本。它包含最後一次呼叫的內容。

您需要將打印分成兩個獨立的呼叫,就像您在以下幾行中所做的那樣。

+0

哦,太棒了。 strtok()V2.0:(( –