2016-04-10 10 views
1

Bir kod yazdım ancak son baskının neden beklenmedik sonuç verdiğini bilmiyorum. Neden printf'de iki kez çağrılan inet_ntoa yanlış çıktı veriyor?

#include <stdio.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

int main(int argc, char *argv[]) 
{ 
    struct in_addr adr, adr2; 
    int num, num2; 

    num = atoi(argv[1]); 
    num2 = atoi(argv[2]); 

    adr.s_addr = htonl(num); 
    adr2.s_addr = htonl(num2); 

    printf("%x %x\n", num, adr.s_addr); # c c000000 
    printf("%x %x\n", num2, adr2.s_addr); # f f000000 

    printf("%s\n", inet_ntoa(adr)); # 0.0.0.12 
    printf("%s\n", inet_ntoa(adr2)); # 0.0.0.15 
    printf("%s %s\n", inet_ntoa(adr), inet_ntoa(adr2)); # 0.0.0.12 0.0.0.12 
    return(0); 
} 

Ben son çıkış "0.0.0.12 0.0.0.15" ama öyle değil olması bekleniyor: My komut satırı argümanları kod aşağıdaki gibidir 12 ve 15. idi. Biri yardım edebilir mi?

cevap

3

inet_ntoa işlevi, bir statik arabelleğe bir işaretçi döndürür. Bu durumda, işlev, başka bir işleve parametre olarak iki kez çağrılır. İşlev parametrelerinin değerlendirilme sırası tanımlanmamıştır, bu nedenle statik arabellek içeriği en son ne zaman olursa olsun olur. Ve her zaman aynı tamponu döndürdüğü için, aynı şey iki kere basılacaktır.

Böylelikle, böyle bir işlevi, araya giren bir sıralama noktası olmaksızın, yani ayrı ifadeler, && veya ||, virgül operatörü veya üçlü operatör gibi kısa devre operatörleri olmaksızın çağırabilirsiniz.

Bu özel kod söz konusu olduğunda, her biri inet_ntoa (tek satırda yaptığınız gibi) için iki ayrı çağrı printf (bunu iki önceki satırlarda yaptığınız gibi) yapmak için doğru yoldur.

Ayrıca, bu işlevin bir sonucunu bir yere kaydetmeyi planlıyorsanız, işaretçiyi kaydedemezsiniz, çünkü işaret ettiği veriler her seferinde değişecektir, çünkü inet_ntoa. strcpy veya strdup kullanarak kopyalamanız gerekir.

+0

Teşekkürler. Bu yardımcı oldu. – anupamb