2012-08-31 43 views
9

Tôi đang bối rối về các dòng mã sau đây:mảng của con trỏ đến char mảng

char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 

Con đường tôi hiểu, mỗi từ là lần đầu tiên lưu trữ và sau đó mỗi vị trí của các mảng words sẽ chỉ sau đó đến đầu tiên tính cách của mỗi từ. Các chuỗi này được lưu trữ như thế nào? Có phân bổ động nào đang diễn ra ở đây hay những từ này được lưu trữ trên ngăn xếp không?

Nếu chúng được lưu trữ trên ngăn xếp, theo cách nào chúng được lưu trữ? Ví dụ, nếu tôi in một số nội dung của words như sau:

#include <stdio.h> 
int main() { 
    char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 
    printf("\n\n(*words)[0] = %s", words[0]); 
    printf("\n\n(*words)[0]+1 = %s", words[0]+1); 
    return 0; 
} 

thay vì in aaabbbb, những gì tôi nhận được là aaaaa. Tôi không thực sự hiểu lý do của việc này là gì, theo cách tôi nhìn thấy, words[0]+1 nên trỏ đến chuỗi bbbb và không phải là ký tự thứ hai của aaa. Chuyện gì đang xảy ra ở đây?

+0

Bạn có nhầm lẫn 'từ [0] + 1', '(từ + 1) [0]' và 'từ [1]'? –

+0

Thử '& words [0] + 1' – oldrinb

Trả lời

2

cách tôi nhìn thấy nó, từ [0] +1 phải trỏ đến các bbbb chuỗi chứ không phải nhân vật thứ hai của aaa

số words[0] là một con trỏ char bản thân - đó là hoàn toàn tốt đẹp bạn sẽ nhận được ký tự thứ hai của "aaa" bằng cách thêm một ký tự vào đó. Những gì bạn muốn là words + 1 hoặc &words[0] + 1 sẽ chính xác là "bbbb".

Ngoài ra, các chuỗi tự được phân bổ khi khởi chạy tệp thực thi và chúng có thể được đặt trong phần dữ liệu hoặc bss của tệp nhị phân bởi trình liên kết. Ngoài ra, khi bạn khai báo và khởi tạo words, nó sẽ được cấp phát trên ngăn xếp như bất kỳ mảng tự động nào khác và các mục của nó sẽ được gán cho con trỏ tới đầu của mỗi hằng số chuỗi.

+0

Tôi hiểu. Tôi thực sự đã thử làm những thứ như 'words [1] [1] = 'u'' để thay đổi' bbbb' thành 'bubb', nhưng' bbbb' vẫn giữ nguyên sau khi tôi thay đổi nó (!). Đây có phải là sau đó bởi vì các chuỗi được đọc chỉ (tôi giả sử họ là vì họ là rvalues)? –

+0

@curvature có chúng. Hãy vui vì nó không sụp đổ - thay đổi hằng số chuỗi là UB. –

3

từ [0] trỏ đến chữ 'a' đầu tiên trong "aaa".

từ [0] +1 di chuyển con trỏ đó theo một ký tự, do đó, nó trỏ đến điểm 'a' thứ hai.

từ [1] điểm tại "bbbb"

từ [1] +1 điểm "bbb", ví dụ chữ 'b' thứ hai trong "bbbb".

0

từ [0] trả về địa chỉ aaa. Thêm 1 vào đó tăng địa chỉ để trỏ đến thứ hai a.

Bạn muốn nói những từ [0 + 1]?

Điều đó sẽ cung cấp cho bạn những gì bạn đang mong đợi.

0
char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 

Tất cả 4 chuỗi có thời lượng lưu trữ tĩnh và được phân bổ trước khi khởi động chương trình.

Trong bộ khởi tạo, các mảng được chuyển đổi thành con trỏ đến char và mảng words được khởi tạo với giá trị con trỏ.

1

Chuỗi ký tự được lưu trữ trong bộ nhớ tĩnh. Vị trí thực tế của chúng là các chuỗi phụ thuộc thực hiện nhưng các chuỗi ký tự được lưu trữ ở đâu đó, thường trong phần dữ liệu của tệp thực thi - đây không phải là phân bổ động hoặc phân bổ ngăn xếp. Mảng của bạn sau đó chứa các con trỏ đến các vị trí này.

từ [0] +1 nên trỏ đến chuỗi bbbb chứ không trỏ đến ký tự thứ hai của aaa.

Cách đơn giản này không phải là cách lập chỉ mục mảng hoạt động. Bạn chỉ mục mảng chuỗi với words[0], bây giờ bạn có một chuỗi và bất kỳ thao tác nào áp dụng cho chuỗi đó. Bạn không thể làm số học với các chỉ số mảng bên ngoài chỉ số. Để truy cập chuỗi "bbbb", bạn sẽ sử dụng words[1].

6

Sự khác biệt là vì words[0]+1 không giống như words[0+1].

Các điểm trước đối với ký tự thứ hai trong words[0], trong khi điểm sau trỏ đến từ thứ hai.

1

Cả không gian ngăn xếp và vùng heap được phân bổ động - tức là chúng được phân bổ vào thời gian chạy. Mã được biên dịch của bạn có được phân bổ động, trên đống hay ngăn xếp không? Rõ ràng là không. Lưu trữ cho các hằng số tương tự như lưu trữ cho mã ... chúng được lưu trữ trong tệp thực thi trên đĩa và được nạp vào bộ nhớ chỉ đọc. (Lưu ý cho người đi bộ: đây là cách mọi thứ được thực hiện trong một thực hiện điển hình; nó không được bắt buộc theo tiêu chuẩn ngôn ngữ.)

words[0] là địa chỉ của 'a' a 'aaaa' đầu tiên. Thêm 1 vào địa chỉ đó chắc chắn sẽ tạo địa chỉ của 'a' thứ hai của "aaaa". Địa chỉ của "bbbb" là cách trên tại words[1].

Ở định dạng printf của bạn, bạn có "(* từ) [0]", nhưng khác nhau. *words giống với words[0]. (*words)[0] giống với **words, đây là 'a' đầu tiên (không phải địa chỉ của nó) là "aaaa". Bạn sẽ in (*words)[0] với %c, không phải %s.

15

này cũng giống như ..

enter image description here

từ từ một loạt các đặc tính của con trỏ vì vậy mỗi chỉ số mảng các từ sẽ giữ địa chỉ của chuỗi đen, tức là. địa chỉ cơ sở của xâu nếu bạn sẽ in

printf("%s",words[0])// index 0 will print aaa. 
Các vấn đề liên quan