Tại sao scanf () lại cần đến %% lf, gấp đôi, khi printf () vẫn ổn với chỉ %% fiên?


179

Tại sao nó scanf()cần l" %lf" khi đọc a double, khi printf()có thể sử dụng " %f" bất kể đối số của nó là a doublehay a float?

Mã ví dụ:

double d;
scanf("%lf", &d);
printf("%f", d);

1
Tôi không hiểu ý của bạn khi ĐIỂM ở đây. Trong scanf, chúng tôi chỉ truyền địa chỉ & biến (tức là), vì vậy con trỏ ở đâu

7
@deetchanya Trong C, khi bạn "lấy địa chỉ" của một biến với toán tử đơn nguyên &, kết quả của thao tác đó là một con trỏ tới vị trí lưu trữ của biến trong bộ nhớ. Đó là con trỏ được truyền vào scanf.
zwol

đây là một bài viết khác liên quan đến stackoverflow.com/questions/9291348/
vimalpt

Câu trả lời:


207

Bởi vì C sẽ thúc đẩy số float tăng gấp đôi cho các hàm có các đối số biến. Con trỏ không được quảng bá cho bất cứ điều gì, vì vậy bạn nên sử dụng %lf, %lghoặc %le(hoặc %latrong C99) để đọc gấp đôi.


26

Do С99, sự phù hợp giữa các chỉ định định dạng và các loại đối số dấu phẩy động trong C là nhất quán giữa printfscanf. Nó là

  • %f cho float
  • %lf cho double
  • %Lf cho long double

Nó chỉ xảy ra khi các đối số của kiểu floatđược truyền dưới dạng tham số matrixdic, các đối số đó được chuyển đổi hoàn toàn thành kiểu double. Đây là lý do tại sao trong printfđịnh dạng định dạng %f%lftương đương và có thể hoán đổi cho nhau. Trong printfbạn có thể "sử dụng chéo" %lfvới floathoặc %fvới double.

Nhưng không có lý do để thực sự làm điều đó trong thực tế. Đừng sử dụng %fđể printftranh luận về loại double. Đó là một thói quen phổ biến được sinh ra từ C89 / 90 lần, nhưng đó là một thói quen xấu. Sử dụng %lftrong printfcho doublevà tiếp tục %fdành cho floatđối số.


1
Tôi sẽ nói rằng sử dụng %ftrong printf là một thói quen tốt bởi vì sau đó mã của bạn luôn hoạt động, trong khi sử dụng %lfcó thể thất bại nếu trình biên dịch không có thư viện tuân thủ C99. Thật không may, tình huống đó xảy ra trong thực tế.
MM

Do С99, sự phù hợp giữa các chỉ định định dạng và các loại đối số dấu phẩy động trong C là nhất quán giữa printfscanf. Lưu ý rằng điều này không có nghĩa là sử dụng cùng một công cụ xác định định dạng có nghĩa là dữ liệu được viết bởi một [f]printf()có thể được đọc bởi [f]scanf(). Nói chung, sử dụng cùng một công cụ xác định định dạng cho scanf()việc sử dụng printf()sẽ không đọc thành công dữ liệu. Ví dụ: phần đệm không gian có thể được chèn bởi trình xác định định dạng prinf()của ' "%d"sẽ bị bỏ qua bởi trình xác "%d"định định dạng tương tự trong scanf()cuộc gọi.
Andrew Henle

16

scanfcần phải biết kích thước của dữ liệu được chỉ ra &dđể điền đúng, trong khi các hàm biến đổi thúc đẩy số float tăng gấp đôi (không hoàn toàn chắc chắn tại sao), vì vậy printfluôn luôn nhận được a double.


1
Một hàm matrixdic rất mong manh, bởi vì nó cần có khả năng biết chính xác loại và kích thước của tất cả các tham số được truyền cho nó và nó không thể thực thi điều này trong thời gian biên dịch. Nếu một biến là loại sai, giá trị sai sẽ được đọc; nếu đó là kích thước sai, tất cả các biến sau đó cũng sẽ bị đọc sai. Nếu hai kích thước nổi khác nhau có thể được thông qua, thì nó sẽ gây ra tất cả các loại vấn đề khó chịu và dễ bỏ sót.
mwfearnley

7

Bởi vì nếu không scanf sẽ nghĩ rằng bạn đang chuyển một con trỏ tới một float có kích thước nhỏ hơn gấp đôi và nó sẽ trả về một giá trị không chính xác.


2

Sử dụng dấu phẩy hoặc giá trị kép trong biểu thức C sẽ dẫn đến giá trị gấp đôi, vì vậy printf không thể cho biết sự khác biệt. Trong khi đó một con trỏ tới một đôi phải được báo hiệu rõ ràng để quétf như khác biệt với một con trỏ để nổi, bởi vì những gì con trỏ trỏ đến là điều quan trọng.


5
float được chuyển đổi thành gấp đôi trong trường hợp này vì các đối số là một phần của danh sách đối số có độ dài thay đổi, số float không phải luôn được chuyển đổi thành gấp đôi trong C.
Robert Gamble

1
Trong các phiên bản tiền chuẩn của các floatgiá trị ngôn ngữ C được tự động thăng cấp thành doublebiểu thức. Quy tắc đó đã bị bỏ qua trong tiêu chuẩn C. Nói chung, floatkhông được quảng bá doubletrong các biểu thức. Nó chỉ được quảng bá doublekhi được thông qua dưới dạng đối số dao động, đó là những gì xảy ra trong trường hợp này.
AnT
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.