2010-02-09 35 views
7

Tôi đang bối rối về mã này: (http://www.joelonsoftware.com/articles/CollegeAdvice.html)Sao chép một chuỗi trong C

while (*s++ = *t++); 

thứ tự thực hiện là gì? Là * s = * t đầu tiên được thực hiện, và sau đó là họ từng tăng? Hay cách khác?

Cảm ơn.

EDIT: Và những gì nếu nó là:

while(*(s++) = *(t++)); 

while(++*s = ++*t); 
+1

Tôi tự hỏi liệu Joel sẽ vẫn đứng cạnh bài viết 5 năm tuổi đó ... quan tâm đến việc bình luận Joel? – Hogan

+0

Tôi đề nghị mọi người bắt đầu đặt dấu chấm phẩy trên dòng tiếp theo, thay vì chỉ sau điều kiện vòng lặp, trong khi các vòng lặp với một câu lệnh rỗng cho cơ thể. Tôi thực sự nghĩ nó rõ ràng hơn và dễ đọc hơn. –

Trả lời

14
while (*s++ = *t++); 

Từ precedence table bạn có thể thấy rõ ++ là có ưu tiên cao hơn *. Nhưng ++ được sử dụng ở đây làm toán tử tăng bài, do đó sự gia tăng xảy ra sau biểu thức gán. Vì vậy, *s = *t xảy ra trước, sau đó s và t được tăng lên.

EDIT:

while(*(s++) = *(t++)); 

là tương tự như trên. Bạn đang làm cho nó rõ ràng hơn với việc sử dụng dấu ngoặc đơn. Nhưng hãy nhớ rằng ++ vẫn là số gia tăng bài đăng.

while(++*s = ++*t); 

Chỉ có một toán tử bên cạnh s. Vì vậy, * được áp dụng trước tiên và trên kết quả đó ++ được áp dụng dẫn đến lỗi lvalue required.

while(*++s = *++t); 

Chỉ cần một toán tử bên cạnh s, t. Vì vậy, sự gia tăng xảy ra đầu tiên theo sau là bản sao. Vì vậy, chúng tôi có hiệu quả bỏ qua bản sao của char đầu tiên từ t đến s.

+0

Không phải là "ưu tiên" và không "ưu tiên"? Nó có thể là một số điều người Anh/Mỹ, vì vậy tôi không muốn chỉnh sửa ... –

2

Các increment là một bài thặng dư. Đăng không chỉ vì nó đến sau khi biến được tăng lên, mà còn bởi vì nó xuất hiện sau khi biểu thức được đánh giá. Vì vậy, thứ tự thực hiện là

*s = *t 

sau đó s ++ và t ++

1

EDIT ::

@chrisgoyal

Trình tự thực hiện là một thuật ngữ mơ hồ. Có hai thứ khác nhau ở đây. Thứ tự cú pháp và ngữ nghĩa của biểu thức.

Cú pháp, toán tử ++ được áp dụng trước tiên. Nếu * s được áp dụng đầu tiên, sau đó những điều sau đây là tương đương với những gì @Hogan nói:

(*s)++ = (*t)++ 

Đó là rất khác biệt so với mẫu của Joel.

Ngữ nghĩa của toán tử ++ là nó được thực thi sau biểu thức.

Hy vọng rằng làm rõ những gì tôi thịt.


Thực tế, s++t++ được áp dụng trước. Đừng quên rằng toán tử sau sửa lỗi được thực thi sau sau. Về cơ bản, toán tử ++ được áp dụng cho cả hai, thì*s = *t được thực thi.

+0

err ... sau khi phương tiện sau khi phải. Bạn đã mô tả sự gia tăng xảy ra trước đó. – Hogan

+0

@Hoạt động sau sửa lỗi có ** mức ưu tiên cao hơn **, vì vậy nó được áp dụng trước tiên. * Ngữ nghĩa * của toán tử sau sửa lỗi được áp dụng * sau * biểu thức được thực hiện. – AraK

+0

Câu trả lời của bạn nói hai điều khác nhau ... – chrisgoyal

4

Bạn nói đúng. * s = * t được thực hiện trước, và sau đó chúng được tăng lên.

0

Trong biến hoạt động tăng Post được sử dụng trước và sau khi biến được sửa đổi.

0

Vì vậy, có hai hình thức tăng

++s // increment before using value 
s++ // increment after using value 

Và kết quả của chúng có thể được dereferenced:

*++s // or... 
*s++ 

này làm việc ra thực sự tốt trên một trong những máy đầu tiên cho C để chạy bật, PDP-11, có chế độ địa chỉ gián tiếp đăng ký làm tăng thanh ghi sau. Các ops sau đã có sẵn trong phần cứng:

*--s // or 
*s++ 

Bạn có thể làm một trong hai

*x++ = *y++; // or 
*--x = *--y; // or some combination 

Và nếu bạn đã làm, toàn bộ dây chuyền đã xảy ra trong một chỉ dẫn duy nhất. Vì // bình luận được giới thiệu bởi C99, tuy nhiên, bạn thực sự không thể thoát khỏi cú pháp nhận xét của tôi.

+0

Bạn có thể lấy đi với các chú thích '//' bằng cách sử dụng 99% trình biên dịch C. Nó không phải là một ý tưởng hay, nhưng tôi nghi ngờ nó sẽ giết bất cứ ai. –

+0

Như thường lệ, bạn đúng, và tôi đồng ý hoàn toàn, nhưng tôi đã suy đoán rằng họ sẽ không làm việc trên trình biên dịch PDP-11 C ... – DigitalRoss

0

Mã: (while *s++ = *t++); là tương đương với:

while (*s = *t) { 
    ++s; 
    ++t; 
} 

Thứ hai là giống hệt nhau - các dấu ngoặc thêm không thay đổi bất cứ điều gì (trong trường hợp này). Để các parens làm bất cứ điều gì, họ sẽ phải như sau: while ((*s)++ = (*t)++);. Điều này sẽ làm tương tự như ví dụ thứ ba của bạn (được trình bày trong đoạn dưới đây).

Ví dụ cuối cùng: while(++*s = ++*t); hoàn toàn khác. Do dereference (*) là gần gũi hơn với toán hạng, điều này dereferences toán hạng, và increments kết quả của dereference, có nghĩa là nó increments những gì con trỏ trỏ AT, thay vì incrementing con trỏ chính nó. Kết quả là, điều này sẽ sao chép ký tự đầu tiên, sau đó tăng ký tự đó, sau đó kiểm tra xem ký tự đó có khác không và tiếp tục như vậy cho đến khi nó bằng không. Kết quả sẽ là cả nguồn và đích sẽ trở thành các chuỗi rỗng (vì ký tự đầu tiên của cả hai giờ sẽ là số 0, được sử dụng để chấm dứt chuỗi).

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