2011-08-30 46 views
6

Các mã sau nhầm lẫn cho tôi một chút:C con trỏ câu hỏi

char * strcpy(char * p, const char * q) { 
while (*p++=*q++); 
//return 
} 

Đây là một thực hiện tước hàm strcpy. Từ mã này, chúng ta thấy rằng con trỏ p và q được tăng cấp, hơn dereferenced và q được gán cho p cho đến khi đạt được \ 0 char. Điều gây nhầm lẫn cho tôi là lần lặp đầu tiên của vòng lặp while. Theo như tôi biết, một con trỏ của mảng điểm đến phần tử đầu tiên của mảng. Trong đoạn mã này, con trỏ được tăng cường trước khi phép gán xảy ra (phải không?), Do đó, từ phần tử đầu tiên của tôi không bao giờ được gán cho p (bởi vì bài viết diễn ra trước khi gán), nhưng nó không và tôi không hiểu phép thuật đằng sau. Bất cứ ai cũng đủ để giải thích tại sao? :-)

Cảm ơn

+6

Định nghĩa của bạn về bài đăng/trước dường như ngược lại. Post = after, Pre = trước. Post-increment ở đây cho thấy ký tự đầu tiên sẽ được sao chép, sau đó con trỏ sẽ được tăng lên. – Marlon

+0

Tại sao thẻ C++ (và tiêu đề)? Đây là một hàm thư viện C. –

+1

Hình như mã C++ hoàn toàn hợp lệ đối với tôi, @Paul. Vậy tại sao * không * thẻ C++? –

Trả lời

9

Vì ++ là sau khi biến, họ không tăng lên cho đến khi sau biểu thức được đánh giá. Đó là lý do tại sao đó là toán tử tăng sau; tiền tố gia tăng là tiền tố (++ p). * ++ p sẽ ghi vào vị trí thứ hai, * p ++ ghi vào vị trí đầu tiên.

+1

Ồ SH *** T, tôi thực sự cần ngủ: S. cảm ơn Kevin: S – Davita

1

Mặt bên phải của biểu thức (* q ++) sẽ được đánh giá trước * p ++ và cả hai sẽ chỉ được tăng lên sau khi quá trình gán diễn ra.

Đọc tuyên bố từ phải sang trái và nhớ tăng sau (q ++ thay vì ++ q) xảy ra sau khi mọi thứ khác trong dòng được giải quyết.

*q --> dereference q 
= --> assign the value 
*p --> to p 

tăng cả hai.

Thực hiện việc này cho đến khi q p lấy phần tử q = 0 là khi nó đạt đến dấu kết thúc null.

2

p++ là tăng dần con trỏ p. Vì vậy, giá trị hiện tại của p được điều hành bởi nhà điều hành deference * trước khi p được tăng lên.

lập luận của bạn sẽ đã đúng nếu vòng lặp while đã được viết như sau:

while (*++p=*++q); 

Trong trường hợp này thặng dư sẽ xảy ra trước khi dereferencing.

2

Không, số gia tăng xảy ra sau khi gán.

Nếu là *(++p), con trỏ p sẽ được tăng lên và sau khi được chỉ định.

1

Đây là việc thực hiện tước chức năng strcpy. Từ mã này, chúng ta thấy rằng con trỏ p và q được tăng cấp, hơn dereferenced và q được gán cho p cho đến khi đạt được \ 0 char.

Nó xảy ra theo cách khác. Giá trị tại *p được đặt thành *q, sau đó cả hai con trỏ đều được tăng lên.

Khi bạn có int foo = bar++ số gia tăng xảy ra sau khi foo đã được đặt.Để có điều đó xảy ra lần đầu tiên bạn sẽ làm gì int foo = ++bar

+1

@Marlon, tại sao bạn chỉnh sửa bài đăng của mình? bạn đã đảo ngược ý nghĩa, điều đó không chính xác. * p được đặt thành * q, không phải là cách khác xung quanh trừ khi tôi có một rắm não hoàn chỉnh và thiếu cái gì đó. – Alex

1

Giá trị của q++ là q
Giá trị của ++qq+1

1

điều kiện Các while vòng lặp được thực hiện sau khi tăng. Một cách tương đương:

while (true) { 
    char* old_p = p; 
    const char* old_q = q; 

    ++p; // or p++; 
    ++q; // or q++; 

    *old_p = *old_q; 
    if (*old_p == '\0') 
     break; 
} 
+0

Không hoàn toàn đúng, vì trong khi bạn (* p) đang xem ký tự tiếp theo, không phải là ký tự vừa được sao chép. – Neil

+0

@Neil - Ahh, ngớ ngẩn tôi. Cảm ơn vì đã bắt! – Dawson

2

Các biểu thức x++++x có cả một kết quả (giá trị) và ảnh hưởng bên.

Kết quả của biểu thức x++ là giá trị hiện tại của x. Hiệu quả bên là nội dung của x được tăng lên bởi 1.

các kết quả của biểu thức ++x là giá trị hiện tại của x cộng 1. Ảnh hưởng bên là tương tự như trên.

Lưu ý rằng tác dụng phụ không cần phải được áp dụng ngay sau khi biểu thức được đánh giá; nó chỉ phải được áp dụng trước điểm chuỗi tiếp theo. Ví dụ, với mã

x = 1; 
y = 2; 
z = ++x + y++; 

không có đảm bảo rằng nội dung của x sẽ được sửa đổi trước khi biểu y++ được đánh giá, hoặc thậm chí trước khi kết quả của ++x + y++ được gán cho z (không phải các = cũng không + khai thác giới thiệu một điểm chuỗi). Biểu thức ++x đánh giá là 2, nhưng có thể biến số x có thể không chứa giá trị 2 cho đến khi sau z đã được chỉ định.

Điều quan trọng cần nhớ là hành vi của các biểu thức như x++ + x++rõ ràng không được xác định theo tiêu chuẩn ngôn ngữ; không có cách nào tốt để dự đoán kết quả của biểu thức sẽ là gì, hoặc giá trị x sẽ chứa sau khi nó được đánh giá.

khai thác Postfix có một ưu tiên cao hơn các nhà khai thác unary, vì vậy biểu thức như *p++ được phân tích cú pháp như *(p++) (nghĩa là bạn đang áp dụng các nhà điều hành * đến kết quả của biểu thức p++). Một lần nữa, kết quả của biểu thức p++ là giá trị hiện tại của p, vì vậy while (*p++=*q++); không bỏ qua phần tử đầu tiên.

Lưu ý rằng toán hạng đối với toán tử tăng/giảm tự động phải là lvalue (về cơ bản, biểu thức đề cập đến vị trí bộ nhớ sao cho bộ nhớ có thể đọc hoặc sửa đổi). Kết quả của biểu thức x++ hoặc ++xkhông phải là một giá trị, do đó bạn không thể viết những thứ như ++x++ hoặc (x++)++ hoặc ++(++x).Bạn có thể viết một cái gì đó như ++(*p++) (p++ không phải là một lvalue, nhưng *p++ là), mặc dù điều đó có thể khiến bạn bị tát bởi bất kỳ ai đọc mã của bạn.