2015-01-30 39 views
7

Nếu một hàm được khai báo làC: làm thế nào để khai báo một hàm tĩnh trả về một chuỗi không tĩnh?

static char *function(...) { ... } 

Liệu nó có nghĩa rằng đây là một chức năng không tĩnh mà trả về một static char *, hoặc một chức năng tĩnh mà trả về một không tĩnh char *?

So sánh hai chức năng sau. Cái nào là sử dụng đúng?

static char *fn1(void) 
{ 
    static char s[] = "hello"; 
    return s; 
} 


static char *fn2(void) 
{ 
    char *s = malloc(6); 
    strcpy(s, "world"); 
    return s; 
} 
+0

'static char *' không phải là loại –

+0

Trên thực tế, 'void' là dư thừa và làm cho một số trình biên dịch bị gián đoạn. –

+0

@ Prof.Falken, tôi nghĩ 'fn1 (void)', trong C89 ít nhất, có nghĩa là tôi khai báo một hàm không có tham số, trong khi 'fn1()' có nghĩa là các tham số không được chỉ định (nghĩa là, trong cũ lần khi ý tưởng về nguyên mẫu chưa được phát minh). Liệu tôi có sai? – hbp

Trả lời

8

static áp dụng cho hàm, không phải kiểu trả về. Cả hai chức năng này đều đúng - sự khác biệt là s sẽ được khởi tạo một lần trong lần gọi đầu tiên đến fn1 và tất cả các cuộc gọi đến fn1 sẽ chia sẻ s; trong khi ở fn2, một s mới sẽ được phân bổ trên mọi cuộc gọi. Và vì cả hai số fn1fn2 đều có liên kết static, chúng sẽ riêng tư đối với đơn vị dịch (tệp nguồn, xấp xỉ) nơi chúng được xác định.

+0

Cảm ơn bạn đã giải thích rõ ràng. – hbp

3

Cả hai định nghĩa chức năng của bạn đều chính xác.

Điểm cần lưu ý, static ở đây được sử dụng để giới hạn hàm đối với phạm vi tệp, không chỉ định loại trả về, tức là chức năng này có thể được sử dụng [gọi] bởi các hàm khác có trong cùng một tệp, chứ không phải bởi các hàm có mặt trong một số tệp khác, mặc dù chúng có thể đã được biên dịch và liên kết với nhau để tạo thành tệp nhị phân.

+0

Cảm ơn bạn đã giải thích. – hbp

3

static trước khi chức năng áp dụng cho các chức năng, không phải loại của nó (hoặc thậm chí một phần của nó, giống như sự trở lại-type):
Nó có nghĩa là chức năng có liên kết tĩnh, aka là dịch đơn vị/tập tin địa phương (và do đó rất có khả năng được inlined).

Cả hai chức năng là chính xác, mặc dù họ có ngữ nghĩa khác nhau:

  • Lợi nhuận đầu tiên một con trỏ đến một mảng tĩnh, có nội dung có thể được sửa đổi. Hãy coi chừng các vấn đề đồng thời và tái nhập nếu bạn làm điều đó.
  • Thứ hai cấp phát một số bộ nhớ heap, khởi tạo nó bằng một chuỗi và trả về điều đó. Hãy nhớ free nó.
+0

Cảm ơn bạn đã trả lời! – hbp

1

Từ khóa static khi được sử dụng với định nghĩa hàm cho biết rằng hàm có phạm vi cấp tệp. Điều này có nghĩa là tên hàm chỉ hiển thị trong chính tệp đó. Từ khóa static được sử dụng trong định nghĩa hàm sửa đổi khả năng hiển thị tên hàm và không sửa đổi kiểu trả về hàm.

Vì vậy, một hàm được khai báo tĩnh có thể trả về bất kỳ loại nào.

Việc sử dụng static trên biến được xác định trong phần thân hàm được sử dụng để cho biết rằng biến sẽ được tạo tại thời điểm ứng dụng được tải và bắt đầu. Vì vậy, nếu bạn sử dụng công cụ sửa đổi static trên một biến trong một hàm, biến đó không được tạo trên ngăn xếp khi hàm được gọi. Nó tồn tại độc lập khi hàm được gọi. Tuy nhiên, khả năng hiển thị của biến chỉ nằm trong hàm.

Trong ví dụ của bạn, bạn có hàm trả về địa chỉ của biến số static. Bạn có thể làm điều này tuy nhiên bạn phải hiểu rằng việc sử dụng này không phải là chủ đề an toàn.Nói cách khác, tất cả các chủ đề gọi hàm sẽ nhận cùng một biến tại cùng một vị trí bộ nhớ và không phải là phiên bản của biến số đó.

Bạn cũng phải hiểu rằng nếu bạn trả lại địa chỉ của biến số static, bạn cũng có thể gây ra sự cố với reentrancy và đệ quy. Lý do là các biến trên stack cung cấp cho reentrancy và đệ quy từ mỗi lần hàm được gọi, một frame mới được thêm vào stack vì vậy mỗi hàm call có frame stack riêng của nó do đó tập hợp các biến riêng của nó.

Đây là một vấn đề được biết đến với cái cũ strtok() hàm trong thư viện chuẩn C mà sử dụng một biến trong strtok() chức năng để duy trì trạng thái giữa các cuộc gọi sử dụng NULL như địa chỉ chuỗi các nơi cuộc gọi cuối cùng để strtok() đã dừng lại khi phân tích cú pháp một chuỗi. Tôi đã nhìn thấy một vấn đề mà một chức năng gọi là strtok() để bắt đầu phân tích một chuỗi và sau đó được gọi là một chức năng mà lần lượt được gọi là strtok() để bắt đầu phân tích cú pháp một chuỗi khác nhau. Kết quả là một số lỗi thực sự lạ và hành vi cho đến khi nguyên nhân được tìm ra.

Sử dụng công cụ sửa đổi static trên biến toàn cục trong tệp sẽ tạo ra biến toàn cầu có thể được chia sẻ bởi nhiều hàm trong tệp. Tuy nhiên, giống như sử dụng công cụ sửa đổi tĩnh trên tên hàm, biến số static sẽ chỉ hiển thị phạm vi tệp.

// .. top of a file of C source code 

static int aStaticInt = 0; // a static int that can be shared by all functions in the file but is visible only in the file 
int aNonStaticInt = 0; // a non static int that is visible outside of the file 

static int myStaticFunc (void) 
{ 
    // a function that is visible only within the file 
} 

int myNonStaticFunc (void) 
{ 
    // a function that is visible outside the file as well as inside the file 
} 
+0

Cảm ơn bạn đã giải thích kỹ lưỡng! – hbp

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