2012-03-09 96 views
43

Tôi đang thực hiện một bài tập trong đó chúng ta phải đọc một chuỗi các chuỗi từ một tệp vào một mảng. Tôi phải gọi một thuật toán mã hóa trên mảng (mật mã chuyển đổi mảng 2D). Vì vậy, lúc đầu tôi đặt tất cả các thông tin từ tập tin vào một mảng 2D, nhưng tôi đã có rất nhiều rắc rối với các loại xung đột trong phần còn lại của mã của tôi (đặc biệt cố gắng để đặt char [] để char *). Vì vậy, tôi quyết định chuyển sang một loạt các con trỏ, điều này giúp mọi thứ dễ dàng hơn rất nhiều trong hầu hết mã của tôi.Có thể chuyển đổi char [] thành char * trong C?

Nhưng bây giờ tôi cần phải chuyển đổi char * thành char [] và ngược lại, nhưng tôi không thể tìm ra. Tôi đã không thể tìm thấy bất cứ điều gì trên google. Tôi bắt đầu tự hỏi nếu nó thậm chí có thể.

+1

Đọc phần 6 của [comp.lang.c FAQ] (http://c-faq.com/). –

Trả lời

87

Có vẻ như bạn đang nhầm lẫn giữa các con trỏ và mảng. Con trỏ và mảng (trong trường hợp này char *char []) là not the same thing.

  • Một mảng char a[SIZE] nói rằng giá trị tại vị trí của a là một mảng có độ dài SIZE
  • Một con trỏ char *a; nói rằng giá trị tại vị trí của a là con trỏ đến số char. Điều này có thể được kết hợp với con trỏ số học để hành xử như một mảng (ví dụ, a[10] là 10 mục qua bất cứ nơi nào a điểm)

Trong trí nhớ, nó trông giống như thế này (ví dụ lấy từ the FAQ):

char a[] = "hello"; // array 

    +---+---+---+---+---+---+ 
a: | h | e | l | l | o |\0 | 
    +---+---+---+---+---+---+ 

char *p = "world"; // pointer 

    +-----+  +---+---+---+---+---+---+ 
p: | *======> | w | o | r | l | d |\0 | 
    +-----+  +---+---+---+---+---+---+ 

Thật dễ nhầm lẫn về sự khác biệt giữa con trỏ và mảng, bởi vì trong nhiều trường hợp, tham chiếu mảng "phân rã" thành con trỏ đến phần tử đầu tiên. Điều này có nghĩa rằng trong nhiều trường hợp (chẳng hạn như khi được truyền cho một cuộc gọi hàm) các mảng trở thành con trỏ. Nếu bạn muốn biết thêm, this section of the C FAQ describes the differences in detail.

Một sự khác biệt thực tế chính là trình biên dịch biết một mảng dài bao lâu. Sử dụng các ví dụ trên:

char a[] = "hello"; 
char *p = "world"; 

sizeof(a); // 6 - one byte for each character in the string, 
      // one for the '\0' terminator 
sizeof(p); // whatever the size of the pointer is 
      // probably 4 or 8 on most machines (depending on whether it's a 
      // 32 or 64 bit machine) 

Nếu không thấy mã của bạn, bạn nên chuyển sang sử dụng con trỏ ở mọi nơi sẽ giải quyết được sự cố bạn đang gặp phải.Lưu ý rằng bây giờ:

  • Bạn sẽ cần phải khởi tạo bộ nhớ ở bất kỳ nơi nào mảng sử dụng. Ví dụ: char a[10]; sẽ trở thành char *a = malloc(10 * sizeof(char));, tiếp theo là séc là a != NULL. Lưu ý rằng bạn không thực sự cần phải nói sizeof(char) trong trường hợp này, bởi vì sizeof(char) được định nghĩa là 1. Tôi đã để nó đầy đủ.

  • Anywhere bạn trước đây đã sizeof(a) cho chiều dài mảng sẽ cần phải được thay thế bằng chiều dài của bộ nhớ mà bạn phân bổ (nếu bạn đang sử dụng chuỗi, bạn có thể sử dụng strlen(), mà đếm lên đến '\0').

  • Bạn sẽ cần thực hiện cuộc gọi tương ứng tới free() cho mỗi cuộc gọi đến malloc(). Điều này nói với máy tính bạn đang thực hiện bằng cách sử dụng bộ nhớ bạn yêu cầu với malloc(). Nếu con trỏ của bạn là a, chỉ cần viết free(a); tại một điểm trong mã mà bạn biết bạn không còn cần bất cứ điều gì a trỏ tới.

Như câu trả lời khác chỉ ra, nếu bạn muốn để có được địa chỉ của người khởi đầu của một mảng, bạn có thể sử dụng:

char* p = &a[0] 

Bạn có thể đọc là "char trỏ p trở thành địa chỉ của phần tử [0] của a ".

+7

+1 Câu trả lời hay nhất –

+0

Trong ví dụ cuối, không thể đơn giản hóa 'char * p = & a [0]' thành 'char * p = & a'? –

+1

@thom_nic: Không, bởi vì '& a' có kiểu' char (*) [6] ', tức là một con trỏ tới một mảng gồm sáu ký tự. Điều này không giống như 'char *', vì vậy bạn sẽ nhận được một cảnh báo. Tuy nhiên, bạn có thể nói 'char * p = a;', bởi vì tham chiếu mảng có thể [phân rã thành con trỏ thành phần tử đầu tiên] (http://c-faq.com/aryptr/aryptrequiv.html). Tôi đã sử dụng hình thức dài hơn ở đây, bởi vì nó minh họa tốt hơn những gì đang xảy ra. –

9

Nếu bạn có char[] c sau đó bạn có thể làm char* d = &c[0] và truy cập yếu tố c [1] bằng cách làm *(d+1) vv

+0

oh, cảm ơn! Tôi sẽ thử xem. – tparf

+0

Hoặc bạn chỉ có thể 'char * d = c;'. – mah

-4

Vâng, tôi không chắc chắn để hiểu câu hỏi của bạn ...

Trong C, Char [] và Char * giống nhau.

Chỉnh sửa: cảm ơn vì liên kết thú vị này.

+2

Tôi e rằng điều đó không đúng - [con trỏ và mảng không giống nhau trong C] (http://www.lysator.liu.se/c/c-faq/c-2.html) –

+0

Tôi nghĩ vậy quá, nhưng trình biên dịch cho tôi một lỗi: ( – tparf

+0

@TimothyJones: Một liên kết tốt hơn cho Câu hỏi thường gặp là http://c-faq.com/. Và tất nhiên bạn đúng 100%: mảng và con trỏ là * không * Điều tương tự (Và nó được đánh vần là 'char', không phải' Char'; nó quan trọng.) –

2

Bạn không cần khai báo chúng dưới dạng mảng nếu bạn muốn sử dụng chúng làm con trỏ. Bạn có thể chỉ đơn giản là tham chiếu con trỏ như thể chúng là mảng đa chiều. Chỉ cần tạo nó như một con trỏ đến một con trỏ và sử dụng malloc:

int i; 
int M=30, N=25; 
int ** buf; 
buf = (int**) malloc(M * sizeof(int*)); 
for(i=0;i<M;i++) 
    buf[i] = (int*) malloc(N * sizeof(int)); 

và sau đó bạn có thể tham khảo buf[3][5] hoặc bất cứ điều gì.

+3

Đừng bỏ kết quả của 'malloc()'. –

+0

Nó là cần thiết bởi vì 'malloc()' trả về một 'void *', mà cần phải được đúc thành một 'int *' được lưu trữ trong 'buf'. – Arcinde

+4

Không, dàn diễn viên là không cần thiết. Trong C, một biểu thức của kiểu 'void *' có thể được chuyển đổi hoàn toàn sang bất kỳ kiểu pointer-to-object (hoặc pointer-to-incomplete) nào. Xem câu hỏi 7.7b của [comp.lang.c FAQ] (http://c-faq.com/) và phần 6.5.16.1 của [C standard] (http://www.open-std.org/ jtc1/sc22/wg14/www/docs/n1570.pdf). (C++ có các quy tắc khác nhau, có liên quan nếu chúng ta đang thảo luận về C++.) –

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