2009-04-30 33 views
11

Tôi đã làm một bài tập cho trường đại học nơi tôi phải trả lại một giá trị với lối ra, giá trị đó thực sự là một thứ gì đó. Điều này có thể cao hơn 255 (mà lối ra() không thể xử lý) nhưng giáo viên đề xuất sử dụng dữ liệu thử nghiệm mà số lượng không bao giờ có thể vượt quá giá trị đó. Sau khi tất cả điều này, tôi cần phải xử lý giá trị đếm này, trạng thái thoát, tôi nhận giá trị này trong quá trình chính bằng cách sử dụng waitpid(). Trước sự ngạc nhiên của tôi, nếu quá trình con trở về 1, giá trị "thực" trong quá trình chính là 256, 2 là 512 và cứ thế ...Bất kỳ lợi ích nào khi sử dụng macro WEXITSTATUS trong C trên phân chia 256 trên trạng thái exit()?

Tôi cần in giá trị này vì vậy tôi đơn giản chia nó cho 256 và Nó được làm xong rồi. Tuy nhiên, nếu tôi sử dụng WEXITSTATUS() vĩ mô, tôi sẽ cũng nhận được giá trị này theo cách tôi muốn nó ...

Tôi nhìn mã nguồn C và đây là những gì tôi phát hiện ra:

#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) 

Tôi hiểu những gì đang xảy ra ở đây, ví dụ, 512 trong nhị phân là 10 0000 0000, dịch chuyển 8 o bên phải sẽ cho 00 0000 0010, là 2 trong thập phân. Những gì tôi không hiểu trong vĩ mô này là nhà điều hành & và thực tế là 0xff00 có vẻ là một số ngẫu nhiên (nó có lẽ không phải là, nó đến từ đâu?). Điều này làm gì chính xác, tại sao có "& 0xff00" trong macro? Nó sẽ không hoạt động với nó?

Và câu hỏi thực sự trong chủ đề này, là điều tương tự để gọi macro này trong mã của tôi khi chia cho 256?

Trả lời

16

Và câu hỏi thực tế trong chủ đề này, là điều tương tự để gọi macro này trong mã của tôi bằng cách chia cho 256?

Nó có thể sẽ luôn hoạt động trong trường hợp quá trình con chấm dứt bình thường (tức là, bằng cách gọi exit(), không phải do lỗi phân đoạn, lỗi xác nhận, v.v.).

Trạng thái được lưu trữ bởi waitpid() mã hóa cả lý do quy trình con bị chấm dứt và mã thoát. Lý do được lưu trữ trong byte ít quan trọng nhất (thu được bởi status & 0xff) và mã thoát được lưu trữ trong byte tiếp theo (được che bởi status & 0xff00 và được trích xuất bởi WEXITSTATUS()). Khi quá trình kết thúc bình thường, lý do là 0 và vì vậy WEXITSTATUS chỉ tương đương với dịch chuyển bằng 8 (hoặc chia cho 256). Tuy nhiên, nếu quá trình bị giết bởi một tín hiệu (chẳng hạn như SIGSEGV), không có mã thoát, và bạn phải sử dụng WTERMSIG để trích xuất số hiệu từ byte lý do.

2

Ở đây 0xff00 là mặt nạ nhị phân (link text). ANDing nó với một giá trị đặt tất cả các bit bằng không, ngoại trừ byte thứ hai (tính từ bên phải).

Bạn chỉ nên sử dụng WEXITSTATUS trên quy trình được biết là đã thoát bình thường. Thông tin này được cung cấp bởi macro WIFEXITED.

Và câu hỏi thực sự trong chủ đề này, là điều tương tự để gọi macro này trong mã của tôi khi chia cho 256?

Macro làm cho mã dễ đọc hơn và được đảm bảo hoạt động trên bất kỳ triển khai tuân thủ Posix nào. Theo tôi biết Posix không chỉ định định dạng của trạng thái, vì vậy bạn không thể mong đợi mã của bạn hoạt động ở mọi nơi.

3

Nếu biến trạng thái là số nguyên 16 bit có chữ ký ('ngắn') trên máy có 'int' là số lượng 32 bit và nếu trạng thái thoát nằm trong phạm vi 128,.255 thì WEXITSTATUS() vẫn cung cấp cho bạn một giá trị đúng khi chia cho 256 hoặc đơn giản dịch chuyển sang phải sẽ cho bạn giá trị không chính xác.

Điều này là do chữ viết tắt sẽ được mở rộng thành 32 bit và mặt nạ sẽ hoàn tác phần mở rộng dấu, để lại giá trị đúng (dương) trong kết quả.

Nếu máy sử dụng số nguyên 16-bit, sau đó các mã trong WEXITSTATUS() có lẽ làm SHIFT sau đó mặt nạ để đảm bảo hành vi tương tự:

#define WEXITSTATUS(status) (((status)>>8) & 0xFF) 

Đó là vì việc thực hiện chăm sóc của các chi tiết đó cho bạn bạn nên sử dụng macro WEXITSTATUS().

3

Theo như tôi có thể biết từ việc kiểm tra đơn Unix Spec, hệ thống của bạn xảy ra để lưu trữ trạng thái thoát trong octet thứ hai đến tận cùng, nhưng tôi không tin là the standard. Vì vậy, bạn nên sử dụng macro cho ít nhất một vài lý do:

  • Chúng đúng. Bit-shifting một số âm làm những việc khác nhau trên các nền tảng khác nhau. Nó có hoạt động theo cách bạn muốn trên máy của bạn không? Tôi không biết.
  • Chúng đơn giản. Ngay lập tức của nó rõ ràng những gì WEXITSTATUS nào. Ít hơn với các cách tiếp cận khác. Nếu bạn thấy phiên bản được cán bằng tay của WIFSIGNALED, bạn có nhận ra nó không? Mất bao lâu hơn WIFSIGNALED.
  • Chúng di động. Kể từ khi làm thế nào spec nói để làm điều đó, nó sẽ làm việc trên mọi hệ thống (ít nhất là khá nhiều mọi hệ thống giống như Unix).
Các vấn đề liên quan