2009-08-04 39 views
26

Làm cách nào để xác định xem một số nguyên chưa được gán chưa?C - Kiểm tra xem Số nguyên có được gán

int i; /* no assignment */ 

if (/* conditional statement here to check if int i is unassigned or not */) { 
    printf("Integer is unassigned!\n"); 
} else { 
    printf("Integer is assigned!\n"); 
} 
+2

Chủ đề này có một số cuộc thảo luận về điều này: http://stackoverflow.com/questions/473236/check-for-value-definedness-in-c – Laserallan

Trả lời

20

Bạn không thể. Nó sẽ có nội dung "không xác định", có nghĩa là nó sẽ chứa những gì từng xảy ra ở vị trí bộ nhớ đó tại thời điểm đó.

. . . trừ khi tôi được khai báo ở phạm vi toàn cầu, thì nó sẽ được khởi tạo thành Zero.

+0

@Kenny: "trừ khi tôi được tuyên bố" thực sự là những gì tôi muốn nói rằng, "i" là biến mà chúng ta đang nói đến, cảm ơn. –

+0

Trên thực tế, tôi nghĩ rằng người ta có thể lập luận rằng ngay cả một biến tĩnh chưa được gán (dĩ nhiên là không được khởi tạo) nếu bạn không khởi tạo nó một cách rõ ràng. –

+0

@Neil: Bây giờ bạn đang lang thang vào một thế giới ngữ nghĩa. MỌI NGƯỜI (kể cả tôi) biết ý nghĩa của việc gán một giá trị. MỌI NGƯỜI cũng biết ý nghĩa của việc khởi tạo biến. Bây giờ, hãy hỏi mọi người "Whats khác nhau giữa phân công và khởi tạo?" và xem chúng cá bơn (đầu của tôi cũng bắt đầu bị tổn thương). –

8

C không thực sự hỗ trợ điều này - giống như nó không thực sự hỗ trợ giới hạn kiểm tra trên mảng. Đó là một sự cân bằng giữa tốc độ/hiệu quả và độ an toàn.

Nói chung ... hãy khởi tạo biến của bạn.

4

Nếu i là toàn cầu hoặc tĩnh, giá trị của nó sẽ là 0, nếu không giá trị của nó có thể là bất kỳ thứ gì và không có cách nào để tìm hiểu xem đó có phải là rác hay không.

1

Thông thường các biến được đặt thành 0 bởi thư viện C, nhưng không nhất thiết.

Nhưng về cơ bản, bạn không thể. Gán cho họ một giá trị mặc định trong định nghĩa, ví dụ:

int i = 0; /* Or what ever value you know won't be used elsewhere */ 

Sau đó, nếu bạn chạy một số mã và muốn kiểm tra nếu giá trị đã được thiết lập ở đó, bạn có thể so sánh với giá trị ban đầu của bạn.

+0

Xem thông báo này, ví dụ: http://gcc.gnu.org/ml/gcc-help/2007-07/msg00097.html – Makis

+0

Và nói như vậy, tôi không có nghĩa là bất kỳ ai cũng nên tin rằng điều này xảy ra. Nếu bạn cần một biến là 0, đặc biệt khởi tạo biến đó thành giá trị đó! – Makis

7

Rất đơn giản. Bạn biết nó chưa được gán bởi vì bạn không khởi tạo nó.

+8

Rõ ràng, vì bạn không bao giờ có biến được đặt trong thời gian chạy. –

0

Trong C, một số nguyên có giá trị không xác định khi được tạo. Điều này có nghĩa là nếu lần đầu tiên bạn sử dụng số nguyên đó xuất phát từ vị trí/thiết bị ghi/bộ nhớ với 5893872 trong đó, đó là giá trị của số nguyên đó. (Mileage khác nhau cho debug/release biên dịch.)

Phương pháp thông thường để đối phó với điều này là sử dụng một mặc định vô nghĩa:

int number_of_widgets = -1; 

... hoặc một lá cờ để chỉ trạng thái của nó:

int number_of_widgets; 
int number_of_widgets_assigned = 0; 

if (number_of_widgets_assigned) 
    do something 
else 
    do something else 
number_of_widgets_assigned = 1; 

Không có cách nào khác để phát hiện xem có điều gì đã được gán hay không - trừ khi bạn muốn truy cập vào các tính năng gỡ lỗi của phần cứng và tôi nghi ngờ đó không phải là nội dung của cuộc trò chuyện này.

1

Như tất cả các câu trả lời trước đó, không có cách nào để phát hiện ra khi chạy. Tuy nhiên, hầu như bất kỳ static code analysis tool nào đều cảnh báo bạn về các biến chưa được gán.

4

Bạn có thể yêu cầu cảnh báo trình biên dịch nếu bạn sử dụng giá trị chưa được khởi tạo. Tuy nhiên, chúng không hoàn toàn đáng tin cậy - bạn sẽ nhận được thông tin không đúng lúc mà DFA không thông minh như bạn mong đợi, và có thể có những âm bản sai (thỉnh thoảng tôi hy vọng là không, nhưng tôi không hứa gì cả).

Đối với GCC:

-Wuninitialized -O1 

Nếu bạn muốn viết mã có điều kiện:

int a = 3; 
int b; 
int *p = (rand() > RAND_MAX/2) ? &a : &b; 
if (is_uninitialized(*p)) // blah 

sau đó bạn đang trên may mắn.Không giống như một số ngôn ngữ động, C không có khái niệm "giá trị không xác định". Nếu một biến không được khởi tạo, nó không được đưa ra một số giá trị đặc biệt có thể được kiểm tra sau này. Nó không được đưa ra một giá trị nào cả, do đó, nó không xác định những gì sẽ xảy ra khi bạn sử dụng biến.

1

Sử dụng biến trước khi intialization (hoặc chuyển nhượng) là nguyên nhân nghiêm trọng của lỗi. Bạn không thể kiểm tra nó một cách đáng tin cậy khi chạy, nhưng bạn có thể phát hiện nó trong hoặc trước khi biên dịch.

Tôi đề xuất không để kiểm tra bên trong mã. Bởi vì điều này có thể gây ra cảnh báo trình biên dịch (Biến 'i' được sử dụng trước khi nó được gán một giá trị), giới thiệu các lỗi mới và có rất ít cơ hội thành công trong các chương trình trung bình đến lớn.

Phương pháp tốt nhất là sử dụng các công cụ phân tích mã tĩnh (như QA/C hoặc PCLint). Sử dụng trình biên dịch ở mức nhạy cảm cảnh báo cao là tùy chọn miễn phí, với mức độ phù hợp thấp hơn nhiều so với các công cụ chuyên dụng.

Nếu bạn thực hiện đánh giá mã, bạn cũng có thể bao gồm kiểm tra các biến chưa được khởi tạo trên danh sách kiểm tra. Điều này không đảm bảo, nhưng nó sẽ kích hoạt kiểm tra thủ công từ người đánh giá.

Nếu đó là kiểm tra thời gian chạy bạn muốn, thì bạn có thể bắt đầu bằng cách intializing biến thành giá trị ngoài phạm vi. Ví dụ -1 cho một giá trị postive khác. Sau đó, bạn có thể kiểm tra

#define UNASSIGNED_VALUE -1 
    static int number_of_apples = UNASSIGNED_VALUE; 
    if (UNASSIGNED_VALUE == number_of_apples) 
    { 
     // error handling 
    } 

đây không phải là biến 'không được xác định' thực sự, nhưng ít nhất bạn có thể phát hiện xem các phép gán thời gian trong phạm vi pháp lý có được thực hiện hay không.

0

Kiểm tra xem biến bạn đang sử dụng có được khởi tạo (được chỉ định) trong thời gian chạy không nổi tiếng với C. Không có hỗ trợ ngôn ngữ cho nó và thông tin có sẵn trong thời gian chạy đơn giản là không đủ để phát hiện hoàn hảo các giá trị chưa được khởi tạo. Các công cụ phân tích động như Valgrind/Memcheck trải qua các độ dài lớn (như theo dõi từng byte bộ nhớ trong không gian địa chỉ của quá trình của bạn và sau đó kiểm tra mọi cửa hàng để đánh dấu một byte là intiialized) để xác định xem giá trị sử dụng có được khởi tạo hay không vẫn còn nhạy cảm với dương tính giả.

Nếu bạn chỉ cố gắng giảm thiểu các lỗi như vậy trong chương trình của mình, các công cụ phân tích tĩnh như lint có thể thực hiện một công việc hợp lý để thông báo cho bạn biết bạn có đang sử dụng các biến chưa được khởi tạo hay không. Trong thực tế, tôi tin rằng hầu hết các trình biên dịch sẽ làm hết sức mình để nói với bạn khi bạn làm điều này (mặc dù, chúng chắc chắn không hoàn hảo.)

4

Như những người khác đã lưu ý, bạn không thể viết chương trình C phát hiện nếu một trong các biến của riêng nó chưa được khởi tạo và bạn nên cố gắng đảm bảo rằng các biến luôn được khởi tạo.

  • Nếu mục tiêu của bạn là để đảm bảo tất cả các biến được khởi tạo, một công cụ như valgrind có thể phát hiện sử dụng các biến chưa được khởi tạo động, thông qua phân tích thời gian chạy tốn kém.

  • Nếu mục tiêu của bạn là để đảm bảo rằng dữ liệu cá nhân được khởi tạo đúng một lần, phương pháp thông thường là để bảo vệ nó với

    int i; 
    static bool initialized = 0; 
    
    ... 
    if (!initialized) { 
        initialized = 1; 
        i = ... i's initial value ...; 
    } 
    
0

Trong C# Tôi muốn sử dụng:

Nullable<int> i = null; /* null assignment */ 

if (i == null) { 
    printf("Integer is unassigned!\n"); 
} else { 
    printf("Integer is assigned!\n"); 
} 

Bạn không chắc chắn liệu điều này có dịch sang C hay không.

+0

Bạn đang sử dụng cả C# và cú pháp c !, mã này là lai cuz C# không có phương thức được gọi là printf, thay vào đó là Console.Write –

Các vấn đề liên quan