2010-06-07 6 views
9

Tôi có một số mã C:Thứ tự các hoạt động cho tiền gia tăng và sau tăng trong một đối số hàm?

main() 
{ 
    int a=1; 
    void xyz(int,int); 

    xyz(++a,a++);  //which Unary Operator is executed first, ++a or a++? 

    printf("%d",a); 
} 
void xyz(int x,int y) 
{ 
    printf("\n%d %d",x,y); 
} 

Chức năng xyz có hai tham số thông qua tại, ++aa++. Ai đó có thể giải thích chuỗi các hoạt động để giải thích kết quả?

Mã trên in "3 13" hoặc "2 23" tùy thuộc vào trình biên dịch được sử dụng.

+1

Có thể sẽ rõ ràng hơn nếu bạn sử dụng các biến khác nhau trong chương trình mẫu của mình. Ngoài ra, bạn nên đặt "\ n" * sau * các giá trị bạn đang in, không phải trước đó. Điều này sẽ in "2 23" – DevinB

+0

Bạn nên thử cái gì đó rõ ràng hơn. Cú pháp đó khá lạ đối với một con người. Làm cho mã đơn giản, đừng cố gắng viết những thứ phức tạp. – INS

Trả lời

26

Vâng, có hai điều cần xem xét với mã ví dụ của bạn:

  1. Trình tự đánh giá của các đối số chức năng là không xác định, vì vậy cho dù ++a hoặc a++ được đánh giá đầu tiên là thực hiện phụ thuộc.
  2. Sửa đổi giá trị a nhiều lần mà không có điểm chuỗi giữa các sửa đổi dẫn đến hành vi không xác định. Vì vậy, kết quả của mã của bạn là không xác định.

Nếu chúng ta đơn giản hóa mã của bạn và loại bỏ các hành vi không xác định và không xác định, sau đó chúng ta có thể trả lời câu hỏi:

void xyz(int x) { } 

int a = 1; 
xyz(a++); // 1 is passed to xyz, then a is incremented to be 2 

int a = 1; 
xyz(++a); // a is incremented to be 2, then that 2 is passed to xyz 
+0

Có đúng trong trường hợp thứ hai 'a' được cập nhật trước khi hàm được gọi? Tôi biết kết quả của biểu thức * '++ a' là 2, đó là những gì được truyền cho' xyz', nhưng sự hiểu biết của tôi là hiệu ứng phụ có thể không nhất thiết phải được áp dụng trước khi hàm được gọi. –

+2

@ John: Có: có một điểm chuỗi sau khi đánh giá tất cả đối số cho hàm nhưng trước khi hàm được gọi. –

9

Trích dẫn Kernighan & Ritchie, Chương 2.12:

Thứ tự đối số chức năng được đánh giá không được chỉ định, do đó, tuyên bố

printf("%d %d\n", ++n, power(2, n)); /* WRONG */ 

có thể tạo ra các kết quả khác nhau với trình biên dịch khác nhau, tùy thuộc vào cho dù n được tăng trước khi nguồn được gọi. Các giải pháp, tất nhiên, là viết

++n; 
printf("%d %d\n", n, power(2, n)); 

cuộc gọi Chức năng, lồng nhau phân báo cáo, và increment và khai thác sụt lần nguyên nhân '' bên hiệu ứng '' - một số biến được thay đổi như một sản phẩm phụ của của việc đánh giá một biểu thức. Trong bất kỳ biểu thức nào liên quan đến các tác dụng phụ, có thể có phụ thuộc tinh tế theo thứ tự trong biến nào tham gia biểu thức được cập nhật. Một hạnh phúc tình hình được đặc trưng bởi các tuyên bố

a[i] = i++; 

Câu hỏi đặt ra là liệu subscript là giá trị cũ của tôi hay cái mới. Trình biên dịch có thể diễn giải điều này theo các cách khác nhau trong và tạo ra các câu trả lời khác nhau tùy thuộc vào cách giải thích của chúng. Tiêu chuẩn cố ý để lại hầu hết các vấn đề như vậy không xác định. Khi tác dụng phụ (gán cho các biến) diễn ra trong một biểu thức được để lại cho trình biên dịch , vì thứ tự tốt nhất phụ thuộc vào máy kiến ​​trúc.(Tiêu chuẩn không chỉ định rằng tất cả các tác dụng phụ trên các đối số có hiệu lực trước khi chức năng được gọi, nhưng điều đó sẽ không trợ giúp trong lệnh gọi printf ở trên.) đạo đức là mã viết tùy thuộc vào thứ tự đánh giá là thực hành lập trình kém trong bất kỳ ngôn ngữ nào. Đương nhiên, cần để biết những điều cần tránh, nhưng nếu bạn không biết cách chúng được thực hiện trên các máy khác nhau, bạn sẽ không bị cám dỗ để tận dụng lợi thế của việc triển khai cụ thể.

2

unary chuỗi đánh giá điều hành cho một chức năng:

#include <stdio.h> 

void xyz(int x, int y) { 
    printf("x:%d y:%d ", x, y); 
} 

main() { 
    int a; 
    a=1; xyz(++a, a);  printf("a:%d\n", a); 
    a=1; xyz(a, a++);  printf("a:%d\n", a); 
    a=1; xyz(++a, a++);  printf("a:%d\n", a); 
} 

chí đầu ra

x:2 y:2 a:2 
x:2 y:1 a:2 
x:3 y:1 a:3 

Trên hệ thống của tôi. Điều này chỉ ra rằng tham số thứ hai của hàm đang được đánh giá đầu tiên. Bạn không nên dựa vào thứ tự đánh giá các tham số chức năng. Nó không được xác định, do đó, nó sẽ khác nhau trên các hệ thống khác nhau.

Làm tốt việc tìm kiếm một ví dụ tiện lợi về hành vi này.

-1

Đối với các toán tử đơn nhất, có tiền tăng (++ i) và tăng sau (i + +). Đối với tiền gia tăng, giá trị được tăng lên sẽ được thêm trước một thao tác. Ví dụ:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << ++i; 
} 

Trong trường hợp này, sản lượng sẽ là 1. Biến 'i' được tăng lên bởi giá trị của 1 trước khi bất kỳ hoạt động khác ví dụ: 'cout < < ++ i'.

Bây giờ, nếu chúng ta đã làm những bài thặng dư trong cùng chức năng:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << i++; 
} 

Sản lượng sẽ chỉ bằng 0. Điều này là bởi vì thặng dư sẽ xảy ra sau khi phẫu thuật. Nhưng kể từ khi bạn muốn biết về đi qua chúng trong khi các thông số, đây là cách nó sẽ đi:

#include <iostream> 
using namespace std; 
// Function Prototypes 
void PrintNumbers(int, int); 

void main() 
{ 
    int a = 0, b = 0; 
    PrintNumbers(++a, b++); 
} 

void PrintNumbers(int a, int b) 
{ 
    cout << "First number: " << a << endl; 
    cout << "Second number: " << b << endl; 
} 

Khi đi qua trong các biến như thông số, đầu ra sẽ là:

First number: 1 
Second number: 0 

Tôi hy vọng điều này giúp !!