2015-07-24 11 views
6

Ponieważ funkcja zwraca wartość całkowitą za każdym razem, gdy jest używana (liczba znaków zapisana na ekranie), czy nie powinno być obowiązkowe zapisywanie tej wartości w zmiennej int za każdym razem, gdy wywoływana jest printf?Dlaczego nie piszemy int x = printf ("tekst"); ponieważ instrukcja printf() zwraca za każdym razem wartość całkowitą?

Edit:

Jeśli funkcja zwraca pewną wartość, to dlaczego nie C sprawiają, że konieczne do przechowywania wartości w momencie wywołania funkcji?

+2

Możesz zrobić to samo. –

+0

A co byś zrobił z tym numerem? – jonrsharpe

+1

Skompilowałem twój kod, nie otrzymałem błędu ani ostrzeżenia o nieużywanej wartości zwracanej. Jakiego kompilatora używasz i jaki jest błąd? – Barmar

Odpowiedz

1

Jeśli uważasz, że twój program C zostanie przetłumaczony na język asemblerowy (na przykład zbiór x86), odczytanie wartości zwracanej przez funkcję jest tylko kwestią odczytania wartości zapisanej w rejestrze "eax" twój procesor.

Język programowania C został historycznie napisany jako język prosty do analizy i kompilacji na bardzo ograniczonym (na dzisiejsze standardy) komputerze PDP-11.

Early C kompilatory (no, niektórzy z nich) przyjął funkcje zadeklarowane bez typu wrócić i bez powrotu, jak następuje:

myFunc(int *x) 
{ 
    *x = *x + *x; 
} 

Jest to funkcja, że ​​te wczesne kompilatory C byłoby interpretować jako

int myFunc(int *x) 
{ 
    *x = *x + *x; 
    return 0; 
} 

Więc odpowiedź na twoje pytanie może być "ze względu na dotychczasowy kod".

Istnieją jednak sytuacje, w których wartość zwracana powinna lub musi być sprawdzona.

Przepis 16.10 z wytycznych MISRA C stanowi, że: "Jeśli funkcja zwraca informację o błędzie, należy sprawdzić te informacje o błędzie".

Jeśli więc chcesz się upewnić, że printf() coś wydrukował, jeśli używasz zwracanej wartości jako "informacji o błędzie", zgodnie z wytycznymi MISRA, musisz sprawdzić tę wartość.

+0

Kompilatory Early C używały domyślnej reguły int ponieważ były oparte na B, który miał tylko jeden typ danych. To prawdopodobnie jest powód, dla którego słowo kluczowe auto nadal istnieje. –

3

Może być, tylko jeśli jest to konieczne.

Jeśli mamy nie obchodzi, że nie chce używać wartości zwracanej. nie ma sensu przechowywanie tego samego.

+0

Ale jeśli mam swoją własną funkcję, która zwraca wartość int i podczas jej wywoływania nie mam przechowuj to samo, kompilator zwraca błąd. Dlaczego to samo nie obowiązuje dla printf()? – n00b

+1

@ n00b 'kompilator zwraca błąd" ... nie, nie będzie. Może, przy bardzo ścisłym sprawdzaniu, wysłać ostrzeżenie o "zignorowaniu" zwracanej wartości, a możesz włączyć opcję "-Werror". –

+0

Tak, rozumiem. Nie daje błędu, po prostu myślałem, że powinien dać błąd, ponieważ funkcja zwraca wartość int, a ja nie używam tej wartości. Mój błąd. – n00b

2

Jeśli masz pomysł, jak masz zamiar używać X to oczywiście można napisać

int x = printf("text"); 

przeciwnym razie wartość zwracana funkcji jest po prostu odrzucone, ponieważ nie jest używany.

W większości przypadków programiści nie znajdują użytecznej aplikacji zwracającej wartość printf.

Jednak czasami można go użyć na przykład do drukowania tabel z wyrównanymi kolumnami.

Na przykład

int n = printf("%s", SomeString); 

if (n < COLUMN_WIDTH) printf("%*c", COLUMN_WIDTH - n, ' '); 

rozważyć to prosty program

#include <stdio.h> 

int main(void) 
{ 
    const int COLUMN_WIDTH = 20; 

    int n = printf("%s", "Hello"); 
    if (n < COLUMN_WIDTH) printf("%*c", COLUMN_WIDTH - n, ' '); 
    printf("%s", "World"); 
} 

Jego wyjście jest

Hello    World 

Oto kolejny przykład, w którym wartość zwracana printf znajdzie przydatnych aplikacji.

Załóżmy, że trzeba wstawić sekwencję liczb oddzielonych przecinkami jak na przykład

1, 2, 3, 4, 5, 6, 7, 8, 9 

Jak wyjście taką sekwencję używając tylko jednej pętli bez umieszczania wypowiedzi drukowania na zewnątrz pętli?

Oto program, który pokazuje, jak można to zrobić na podstawie wartości zwracanej przez funkcję printf. :) Spróbuj.

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

int main(void) 
{ 
    size_t n = 0; 

    printf("Enter the number of elements in the array (greater than 0): "); 
    scanf("%zu", &n); 

    if (n == 0) exit(1); 

    int a[n]; 

    srand((unsigned int)time(NULL)); 

    size_t i; 

    for (i = 0; i < n; i++) a[ i ] = rand() % n; 

    i = 0; 

    do 
    { 
     printf("%d", a[ i ]); 
    } while (++i < n && printf(", ") > 0); 

    return 0; 
} 

chodzi o programie

int foo(int x) { 
    return x; 
} 
int main() { 
    foo(10); 
} 

następnie wywołując funkcję foo nie ma żadnego wpływu. Nie robi nic, a w rzeczywistości można go usunąć. I nie wszystkie kompilatory wysyłają wiadomość do twojego programu. Wydaje się, że kompilator, którego używasz, ma opcję kompilatora, która wymusza na kompilatorze rozważanie ostrzeżeń takich jak błędy. Twój kompilator chce, abyś zwrócił uwagę, że wywołanie funkcji nie ma żadnego efektu. Możliwe, że popełniłeś błąd logiczny.

Z drugiej strony funkcja wywołania printf ma widoczny efekt.

+0

@ n00b Zobacz mój zaktualizowany wpis. –

+0

Tak, przepraszam. Ponownie zredagowałem pytanie. Co naprawdę chcę wiedzieć, dlaczego to nie C powoduje, że zapisywanie wartości zwracanej przez funkcję jest obowiązkowe? – n00b

+0

@ n00b Zobacz jeszcze jeden mój wpis. :) –

1

Możesz zachować wartość zwracaną, jeśli jej potrzebujesz, na przykład, aby upewnić się, że wypisujesz żądaną liczbę znaków (wydaje się mało prawdopodobne, że ma się takie potrzeby, szczególnie biorąc pod uwagę, że w produkcji zwykle masz bardziej wszechstronną logowanie modułów do obsługi wyjść).

Można też wyraźnie powiedzieć, że nie dbają o tej wartości zwracanej do kompilatora z (void) jak w

(void) printf("hello world\n"); 

Zauważ, że to nie ma wpływu innych niż tłumienie ostrzeżenia niektórych narzędzi (np lint) lint)

1

Jeśli funkcja zwraca pewną wartość, dlaczego C nie powoduje konieczności zapisania wartości w czasie wywołania funkcji?

To chyba gorsze od normalnej C stylu programowania punktu widzenia: Stworzyłeś lokalną zmienną o wartości, ale nie należy go używać:

int x; 
    x = printf(...); 

dałoby ostrzeżenie nie używasz x do niczego. Trzeba będzie to zrobić, aby rozwiązać oba otwarte końce:

if (printf(...)<EXPECTED_OUTPUT_BYTES) exit(1); 

lub podobnie. Na szczęście wyjście nie zwraca niczego.

0

Jak powiedzieli inni, możesz zignorować wynik dowolnego wywołania funkcji.

Jeśli jednak używasz gcc, możesz dodać atrybut funkcji warn_unused_result, który powoduje, że gcc ostrzega, jeśli nie zostanie użyty wynik upuszczenia funkcji. Połącz to z -Werror, a następnie sprawdź, czy są używane wyniki.

Oto przykład ze strony info gcc:

int fn() __attribute__ ((warn_unused_result)); 
int foo() 
{ 
    if (fn() < 0) return -1; 
    fn(); 
    return 0; 
} 

To będzie ostrzegać (lub błąd z -Werror) o wykorzystaniu fn();.