2010-08-18 39 views
5

Tôi đang cố chuyển một chuỗi các chuỗi ký tự (chuỗi kiểu C) vào một hàm. Tuy nhiên, tôi không muốn đặt một kích thước tối đa trên chiều dài của mỗi chuỗi đi vào chức năng, cũng không phải tôi muốn phân bổ các mảng động. Đây là mã tôi đã viết đầu tiên:Chuyển mảng chuỗi ký tự đến hàm

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void fun(char *s[]) 
{ 
    printf("Entering Fun\n"); 
    printf("s[1]=%s\n",(char *)s[1]); 
} 

int main(void) 
{ 
    char myStrings[2][12]; 

    strcpy(myStrings[0],"7/2/2010"); 
    strcpy(myStrings[1],"hello"); 
    fun(myStrings); 

    return(0); 
} 

tôi nhận được một lỗi seg khi chạy và cảnh báo sau đây từ trình biên dịch: stackov.c: Trong chức năng 'chính': stackov.c: 17: cảnh báo: chuyển đối số 1 của 'fun' từ loại con trỏ không tương thích stackov.c: 5: note: expected 'char **' nhưng đối số là kiểu 'char (*) [12]'

Tuy nhiên, khi tôi thay đổi main() đến sau hoạt động:

int main(void) 
{ 
    char myStrings[2][12]; 
    char *newStrings[2]; 

    strcpy(myStrings[0],"7/2/2010"); 
    strcpy(myStrings[1],"hello"); 
    newStrings[0]=myStrings[0]; 
    newStrings[1]=myStrings[1]; 
    fun(newStrings); 

    return(0); 
} 

Không phải mảng [2] [12] cũng giống như một mảng các con trỏ ký tự khi nó được chuyển đến một hàm?

Trả lời

7

Không, char array[2][12] là một mảng hai chiều (mảng của mảng). char *array[2] là một mảng con trỏ.

char array[2][12] trông giống như:

7/2/2010\0\x\x\xhello\0\x\x\x\x\x\x 

nơi \ 0 là NUL và \ x là không xác định.

khi

char *array[2] là:

0x CAFEBABEDEADBEEF 

(giả sử 32-bit)

Đầu tiên có 24 ký tự liền kề, thứ hai có hai con trỏ (tới sự khởi đầu của chuỗi ở nơi khác).

2

Không phải mảng [2] [12] giống với một mảng con trỏ ký tự khi nó được chuyển đến một hàm không?

Không, đó là mảng hai chiều. Sự khác biệt là một mảng con trỏ chứa con trỏ, nhưng array[2][12] thực sự là một mảng các mảng - không có con trỏ nào liên quan.

BTW bạn có thể làm:

char* mystrings[2]={"aha", "haha"}; 
fun(mystrings); 
+0

Điều này có lợi ích là chỉ lưu trữ số lượng ký tự thực tế cần thiết cho các chuỗi. Hạn chế là một con trỏ (bổ sung) cũng được phân bổ cho mỗi chuỗi. Nhưng tính dễ sử dụng của con trỏ là lợi thế chính. –

+0

Có, tôi biết điều này đã làm việc, nhưng đối với ứng dụng thực tế, tôi không thể khởi tạo mảng tại thời gian biên dịch. – Mike

+0

@Mike: Khi bạn sử dụng nó trong một hàm, mảng thực sự được khởi tạo khi chạy. – jpalecek

0

mảng của bạn được khai báo là một mảng 2-D, nhưng bạn muốn vượt qua nó để chức năng như thể đó là một mảng 1-D của con trỏ chuỗi.

Câu trả lời của Tom là chính xác, bạn có thể bỏ qua kích thước của thứ nguyên đầu tiên của khai báo mảng đa chiều cho các tham số hàm.

Giải pháp thứ hai của bạn hoạt động vì nó giải thích rõ ràng một mảng chuỗi 1-D của hàm.Tất nhiên, nó đòi hỏi thêm chi phí của mảng con trỏ ngoài mảng chuỗi 2-D ban đầu.

1

char myStrings[2][12]; tuyên bố myStrings làm mảng mảng ký tự. Điều này có nghĩa rằng myStrings được lưu giữ như 24 byte

7/2/2010.???hello.?????? 
‘——————————’‘——————————’ 
myStrings[0]myStrings[1] 

nơi . đại diện cho một ký tự null và ? đại diện cho một byte chưa được khởi tạo.

char *newStrings[2]; tuyên bố newStrings làm mảng con trỏ cho ký tự. Điều này có nghĩa rằng newStrings được lưu giữ như 2 × sizeof(char*) byte

[..][..] 

nơi [..] đại diện cho một đối tượng con trỏ (chưa khởi tạo).

Nếu bạn muốn chuyển các chuỗi có độ dài khác nhau cho hàm của bạn, bạn phải chuyển một mảng con trỏ, không phải mảng mảng. Như bạn có thể thấy ở trên, đây là các bố cục khác nhau.

Lời khuyên chung: bất cứ khi nào bạn ở xung quanh con trỏ, vẽ sơ đồ (trên bảng trắng hoặc bảng đen nếu bạn có thể, nếu không trên giấy) hiển thị các đối tượng khác nhau trong bộ nhớ. Có hai loại lập trình viên C: những người vẽ sơ đồ như vậy khi họ gặp con trỏ, và những người thực sự có kinh nghiệm vẽ sơ đồ trong đầu họ.

+0

Tôi đang bối rối bởi tuyên bố của bạn: "Lưu ý rằng các cuộc gọi tiếp theo của bạn để strcpy cố gắng để viết cho một con trỏ chưa được uninitialized. Đó là tinh khiết mischance rằng chương trình đã cho kết quả mà bạn muốn thay vì đâm." Ý của bạn là gì? Ngoài ra, bạn đang nhận được gì bằng "con trỏ chưa được khởi tạo"? Cảm ơn – Mike

+0

@ Giống như: Xin lỗi, bit này là một sai lầm về phía tôi (tôi đã hiểu sai mã của bạn). – Gilles

+0

Không sao cả. Tôi chỉ muốn chắc chắn rằng tôi đã không bỏ lỡ một cái gì đó. – Mike

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