2012-04-06 29 views
5

Câu hỏi rất đơn giản, nhưng có lẽ tôi chỉ quên thứ gì đó. Trong Linux 64bit, dài 8bytes là chính xác? Nếu đó là trường hợp, và tôi muốn thiết lập các bit thứ 64, tôi có thể làm như sau:Loại dài 64bit linux

unsigned long num = 1<<63; 

Bất cứ khi nào tôi biên dịch này, tuy nhiên, nó mang lại cho tôi một lỗi nói rằng tôi trái chuyển hơn chiều rộng. Ngoài ra, nếu tôi muốn lấy 32bits đầu tiên của một loại dài (không có phần mở rộng dấu), tôi có thể làm:

num = num&0xFFFFFFFF; 

hoặc những gì về:

num = (int)(num); 

Cảm ơn bạn.

+5

Hãy thử: 'unsigned num dài = 1UL << 63;' – Mysticial

+0

@Mysticial Tại sao không gửi đó như là một câu trả lời cùng với các công cụ xúc tiến số nguyên? – cnicutar

+1

Phụ thuộc vào trình biên dịch được sử dụng. Nhiều trình biên dịch kế thừa sẽ mặc định là 32 bit, ngay cả khi chạy trên máy 64 bit. Xác nhận rằng 'sizeof num' là 8 trước khi thử thêm bất kỳ thứ gì. – wallyk

Trả lời

3

Trong 64bit linux, dài 8bytes đúng?

Không cần thiết. Phụ thuộc vào trình biên dịch hơn là trên hệ điều hành cơ bản. Kiểm tra điều này để có một cuộc thảo luận tốt đẹp. What decides the sizeof an integer?

Bất cứ khi nào tôi biên dịch này, tuy nhiên, nó mang lại cho tôi một lỗi nói rằng tôi trái chuyển hơn chiều rộng

Mọi người đã trả lời câu này. Sử dụng 1UL

Ngoài ra, nếu tôi muốn lấy 32bits đầu tiên của một dài loại (không có phần mở rộng dấu ), tôi có thể làm:

num = num&0xFFFFFFFF; 
or what about: 

num = (int)(num); 

num = num&0xFFFFFFFF. Điều này sẽ cung cấp cho bạn 32 bit thấp hơn. Nhưng lưu ý rằng nếu long chỉ là 4 byte trên hệ thống của bạn thì bạn sẽ nhận được toàn bộ số. Đến phần mở rộng ký hiệu, nếu bạn đã sử dụng long và không phải unsigned long thì bạn không thể loại bỏ các bit mở rộng của dấu. Ví dụ: -1 được thể hiện như tất cả, ngay từ bit thứ 0. Bạn sẽ tránh những cái này bằng cách che mặt bằng cách nào?

num = (int)(num) sẽ cung cấp cho bạn thấp hơn 32-bit nhưng biên dịch có thể thông qua một cảnh báo tràn ngoại lệ nếu num không phù hợp với một mã AFAIR int

+0

Đồng ý rằng C không áp đặt "dài" là 64 bit trên máy 64 bit. Tuy nhiên, Linux ngầm ám chỉ điều đó. Chỉ cần xem xét tất cả các con trỏ được truyền qua 'các giá trị không tồn tại lâu dài và bộ nhớ bù được truyền qua' ký dài' (ví dụ: syscalls). Vì vậy, miễn là mã nguồn Linux không thay đổi đáng kể, tôi sẽ trả lời ** có ** cho câu hỏi: "Trong linux 64bit, một' long' là 8bytes, đúng không? " –

0

Tôi tin rằng vấn đề với câu hỏi đầu tiên là trình biên dịch xử lý '1' làm số nguyên, không phải là số nguyên dài. Nó không tìm ra nó cho đến sau bài tập.

Bạn có thể sửa chữa nó bằng cách thực hiện:

unsigned long num = (unsigned long)1<<63; 
+0

Bạn có biết câu trả lời cho phần thứ hai của câu hỏi của tôi không. Về việc thu được 32 bit đầu tiên không được mở rộng ký hiệu? Tôi sẽ làm một cái gì đó tương tự như num = num & (unsigned long) (0xFFFFFFFF)? – de1337ed

+0

@ de1337ed Tôi đã trả lời phần thứ hai của Qn của bạn. Kiểm tra –

4

Trên thực tế, nếu bạn muốn có một số chiều dài chính xác (theo bit) cho số nguyên của bạn, giả sử một trình biên dịch C99 phù hợp, #include <stdint.h> và sử dụng các loại như int64_t, int32_t vv một loại tiện dụng là intptr_t, một kiểu số nguyên với cùng số bit như void* con trỏ (để bạn có thể gọi nó là một máy "từ")

+1

Trình biên dịch tuân thủ C99 không cần phải cung cấp các loại chiều rộng cố định, ví dụ: 'int64_t'. Chỉ có các bổ sung bổ sung twos cung cấp các kiểu số nguyên 8-, 16-, 32- và 64-bit không có bit đệm là * required * để cung cấp các typedef số nguyên cố định chiều rộng trong 'stdint.h'. – dreamlax

1

Đối với tính di động, bạn có thể sử dụng:

limits.h

#define LNG_BIT (sizeof(long) * CHAR_BIT) 

unsigned long num = 1UL << (LNG_BIT - 1); 

Để có được "thấp int", một cái gì đó giống như ?:

#define INT_BIT (sizeof(int) * CHAR_BIT) 

if (LNG_BIT > INT_BIT) 
    return num & (~0UL >> INT_BIT); 
else 
    return num; 

hoặc

num &= ~(~0U << INT_BIT); 

Hoặc, sử dụng mặt nạ, vv Phụ thuộc lớn vào lý do tại sao, cho những gì, vv bạn muốn các bit int.

Cũng lưu ý các tùy chọn do trình biên dịch đưa ra; I E. nếu bạn đang sử dụng gcc:

-m32
-m64
-mx32
        Tạo mã cho phiên bản 32-bit hoặc Môi trường 64 bit.
        * Tùy chọn -m32 đặt int, dài và kiểu con trỏ thành 32 bit và tạo mã chạy trên bất kỳ hệ thống i386 nào.
        * Tùy chọn -m64 đặt int thành 32 bit và kiểu con trỏ dài đến 64 bit và tạo mã cho kiến ​​trúc x86-64. Đối với Darwin chỉ tùy chọn -m64 cũng tắt các tùy chọn -fno-pic và -mdynamic-no-pic.
        * Tùy chọn -mx32 đặt int, dài và kiểu con trỏ thành 32 bit và tạo mã cho kiến ​​trúc x86-64.

Ngoài ra còn có -maddress-mode=long, vv

-maddress-mode = dài
        Tạo mã cho chế độ địa chỉ dài. Điều này chỉ được hỗ trợ cho các môi trường 64-bit và x32. Đây là chế độ địa chỉ mặc định cho môi trường 64 bit.

0

như thế này là nguồn gốc của một lỗi lớn trong reiserfs một vài năm trước đây :

unsigned long num = 1<<63; 

Nếu bạn nói về x86_64, có, dài 64 bit và trên hầu hết các plytforms 64 bit khác.Vấn đề là cả hai 163 trong mã của bạn là đơn giản int và do đó kết quả là không xác định. Tốt hơn sử dụng

unsigned long num = 1UL<<63; 

hoặc

unsigned long num = (unsigned long)1<<63; 
Các vấn đề liên quan