Ý nghĩa của cả hai đều trốn tránh tôi.
Ý nghĩa của cả hai đều trốn tránh tôi.
Câu trả lời:
Một khai báo giới thiệu một định danh và mô tả loại của nó, có thể là một loại, đối tượng hoặc chức năng. Một khai báo là những gì trình biên dịch cần để chấp nhận các tham chiếu đến định danh đó. Đây là những tuyên bố:
extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations
Một định nghĩa thực sự khởi tạo / thực hiện định danh này. Đó là những gì trình liên kết cần để liên kết các tham chiếu đến các thực thể đó. Đây là các định nghĩa tương ứng với các tuyên bố trên:
int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};
Một định nghĩa có thể được sử dụng ở nơi khai báo.
Một định danh có thể được khai báo thường xuyên như bạn muốn. Do đó, những điều sau đây là hợp pháp trong C và C ++:
double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);
Tuy nhiên, nó phải được xác định chính xác một lần. Nếu bạn quên định nghĩa một cái gì đó đã được khai báo và được tham chiếu ở đâu đó, thì trình liên kết sẽ không biết liên kết tham chiếu đến cái gì và phàn nàn về một biểu tượng bị thiếu. Nếu bạn xác định một cái gì đó nhiều hơn một lần, sau đó mối liên kết không biết mà các định nghĩa để tham khảo liên kết đến và phàn nàn về những biểu tượng trùng lặp.
Vì cuộc tranh luận về khai báo lớp là gì so với định nghĩa lớp trong C ++ sẽ tiếp tục (trong câu trả lời và nhận xét cho các câu hỏi khác), tôi sẽ dán một trích dẫn từ tiêu chuẩn C ++ tại đây.
Tại 3.1 / 2, C ++ 03 nói:
Một khai báo là một định nghĩa trừ khi nó [...] là một khai báo tên lớp [...].
3.1 / 3 sau đó đưa ra một vài ví dụ. Trong số đó:
[Thí dụ: [...] cấu trúc S {int a; int b; }; // định nghĩa S, S :: a và S :: b [...] cấu trúc S; // khai báo S Ví dụ
Tóm lại: Tiêu chuẩn C ++ được coi struct x;
là một tuyên bố và struct x {};
một định nghĩa . (Nói cách khác, "khai báo chuyển tiếp" một cách viết sai , vì không có hình thức khai báo lớp nào khác trong C ++.)
Cảm ơn litb (Johannes Schaub) , người đã đào ra chương thực tế và câu thơ trong một trong những câu trả lời của mình.
extern int i
là một tuyên bố, vì nó chỉ giới thiệu / chỉ định i
. Bạn có thể có bao nhiêu extern int i
trong mỗi đơn vị biên dịch như bạn muốn. int i
tuy nhiên, là một định nghĩa. Nó biểu thị không gian cho số nguyên nằm trong đơn vị dịch thuật này và khuyên người liên kết liên kết tất cả các tham chiếu để i
chống lại thực thể này. Nếu bạn có nhiều hơn hoặc ít hơn chính xác một trong những định nghĩa này, trình liên kết sẽ khiếu nại.
int i;
trong tập tin / phạm vi toàn cầu hoặc phạm vi chức năng là một định nghĩa cả trong C và C ++. Trong C vì nó phân bổ lưu trữ và trong C ++ vì nó không có bộ xác định bên ngoài hoặc đặc tả liên kết. Các số tiền này cho cùng một thứ, đó là những gì sbi nói: trong cả hai trường hợp, khai báo này chỉ định đối tượng mà tất cả các tham chiếu đến "i" trong phạm vi đó phải được liên kết.
struct A { double f(int, double); double f(int, double); };
không hợp lệ, tất nhiên. Nó được cho phép ở nơi khác mặc dù. Có một số nơi bạn có thể khai báo mọi thứ, nhưng cũng không xác định: void f() { void g(); }
hợp lệ, nhưng không phải là sau : void f() { void g() { } };
. Định nghĩa là gì và những gì một tuyên bố có các quy tắc tinh tế khi nói đến các mẫu - hãy cẩn thận! +1 cho một câu trả lời tốt mặc dù.
Từ phần chuẩn C ++ 3.1:
Một tuyên bố giới thiệu tên vào một đơn vị dịch thuật hoặc xác định lại tên được giới thiệu bởi các tuyên bố trước đó. Một tuyên bố chỉ định việc giải thích và các thuộc tính của những tên này.
Đoạn tiếp theo (nhấn mạnh của tôi) rằng một tuyên bố là một định nghĩa trừ khi ...
... nó khai báo một hàm mà không chỉ định phần thân của hàm:
void sqrt(double); // declares sqrt
... nó tuyên bố một thành viên tĩnh trong định nghĩa lớp:
struct X
{
int a; // defines a
static int b; // declares b
};
... nó tuyên bố một tên lớp:
class Y;
... Nó chứa extern
từ khóa mà không có bộ khởi tạo hoặc thân hàm:
extern const int i = 0; // defines i
extern int j; // declares j
extern "C"
{
void foo(); // declares foo
}
... Hoặc là một typedef
hoặc một using
tuyên bố.
typedef long LONG_32; // declares LONG_32
using namespace std; // declares std
Bây giờ vì lý do lớn tại sao điều quan trọng là phải hiểu sự khác biệt giữa một tuyên bố và định nghĩa: Quy tắc Một Định nghĩa . Từ mục 3.2.1 của tiêu chuẩn C ++:
Không có đơn vị dịch thuật nào chứa nhiều hơn một định nghĩa về bất kỳ biến, hàm, loại lớp, kiểu liệt kê hoặc mẫu.
struct x {static int b = 3; };
?
b
cũng được tuyên bố const
. Xem stackoverflow.com/a/3536513/1858225 và daniweb.com/software-development/cpp/threads/140739/ Lỗi .
Tuyên bố: "Ở đâu đó, tồn tại một foo."
Định nghĩa: "... và đây rồi!"
Có những trường hợp cạnh thú vị trong C ++ (một số trong C cũng vậy). Xem xét
T t;
Đó có thể là định nghĩa hoặc khai báo, tùy thuộc vào loại T
:
typedef void T();
T t; // declaration of function "t"
struct X {
T t; // declaration of function "t".
};
typedef int T;
T t; // definition of object "t".
Trong C ++, khi sử dụng các mẫu, có một trường hợp cạnh khác.
template <typename T>
struct X {
static int member; // declaration
};
template<typename T>
int X<T>::member; // definition
template<>
int X<bool>::member; // declaration!
Tuyên bố cuối cùng không phải là một định nghĩa. Đó là tuyên bố về một chuyên môn rõ ràng của thành viên tĩnh của X<bool>
. Nó nói với trình biên dịch: "Nếu nói đến việc khởi tạo X<bool>::member
, thì đừng khởi tạo định nghĩa của thành viên từ mẫu chính, mà sử dụng định nghĩa được tìm thấy ở nơi khác". Để làm cho nó một định nghĩa, bạn phải cung cấp một bộ khởi tạo
template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
Tờ khai
Các khai báo cho trình biên dịch biết rằng một phần tử hoặc tên chương trình tồn tại. Một tuyên bố giới thiệu một hoặc nhiều tên vào một chương trình. Tuyên bố có thể xảy ra nhiều lần trong một chương trình. Do đó, các lớp, cấu trúc, kiểu liệt kê và các kiểu do người dùng định nghĩa khác có thể được khai báo cho mỗi đơn vị biên dịch.
Định nghĩa
Định nghĩa xác định mã hoặc dữ liệu mà tên mô tả. Một tên phải được khai báo trước khi nó có thể được sử dụng.
class foo {};
là một định nghĩa lớp , phải không?
Từ tiêu chuẩn C99, 6,7 (5):
Một khai báo chỉ định việc giải thích và các thuộc tính của một bộ định danh. Một định nghĩa của một định danh là một tuyên bố cho định danh đó:
Từ tiêu chuẩn C ++, 3.1 (2):
Một khai báo là một định nghĩa trừ khi nó khai báo một hàm mà không chỉ định thân của hàm, nó chứa hàm xác định bên ngoài hoặc một đặc tả liên kết và không phải là trình khởi tạo cũng như thân hàm, nó khai báo một thành viên dữ liệu tĩnh trong khai báo lớp, nó là một khai báo tên lớp, hoặc nó là một khai báo typedef, khai báo sử dụng hoặc chỉ thị sử dụng.
Sau đó là một số ví dụ.
Thật thú vị (hoặc không, nhưng tôi hơi ngạc nhiên về nó), typedef int myint;
là một định nghĩa trong C99, nhưng chỉ là một tuyên bố trong C ++.
typedef
, điều đó có nghĩa là nó có thể được lặp lại trong C ++, nhưng không phải trong C99?
Từ wiki.answers.com:
Thuật ngữ khai báo có nghĩa (trong C) mà bạn đang nói với trình biên dịch về loại, kích thước và trong trường hợp khai báo hàm, loại và kích thước của các tham số của bất kỳ biến nào, hoặc loại hoặc hàm do người dùng xác định trong chương trình của bạn. Không có không gian được dành riêng trong bộ nhớ cho bất kỳ biến nào trong trường hợp khai báo. Tuy nhiên, trình biên dịch biết có bao nhiêu không gian để dự trữ trong trường hợp một biến loại này được tạo.
ví dụ, sau đây là tất cả các khai báo:
extern int a;
struct _tagExample { int a; int b; };
int myFunc (int a, int b);
Mặt khác, định nghĩa có nghĩa là ngoài tất cả những điều khai báo, không gian cũng được dành riêng trong bộ nhớ. Bạn có thể nói "ĐỊNH NGH = A = KHAI THÁC + ĐỔI KHÔNG GIAN" sau đây là các ví dụ về định nghĩa:
int a;
int b = 0;
int myFunc (int a, int b) { return a + b; }
struct _tagExample example;
xem câu trả lời .
struct foo {};
là một định nghĩa , không phải là một tuyên bố. Một tuyên bố foo
sẽ được struct foo;
. Từ đó, trình biên dịch không biết cần bao nhiêu dung lượng cho foo
các đối tượng.
struct foo;
là một khai báo, nhưng nó không cho trình biên dịch biết kích thước của foo. Tôi muốn thêm đó struct _tagExample { int a; int b; };
là một định nghĩa. Vì vậy, trong bối cảnh này, thật sai lầm khi gọi nó là một tuyên bố. Tất nhiên nó là một, vì tất cả các định nghĩa là khai báo, nhưng dường như bạn đang gợi ý rằng nó không phải là một định nghĩa. Đó là một định nghĩa, của _tagExample.
Vì tôi không thấy câu trả lời thích hợp cho C ++ 11 ở đây.
Một khai báo là một định nghĩa trừ khi nó khai báo a / n:
enum X : int;
template<typename T> class MyArray;
int add(int x, int y);
using IntVector = std::vector<int>;
static_assert(sizeof(int) == 4, "Yikes!")
;
Các mệnh đề bổ sung được kế thừa từ C ++ 03 theo danh sách trên:
int add(int x, int y);
extern int a;
hoặcextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Một khai báo mẫu là một khai báo. Một khai báo mẫu cũng là một định nghĩa nếu khai báo của nó định nghĩa một hàm, một lớp hoặc một thành viên dữ liệu tĩnh.
Các ví dụ từ tiêu chuẩn phân biệt giữa khai báo và định nghĩa mà tôi thấy hữu ích trong việc tìm hiểu các sắc thái giữa chúng:
// except one all these are definitions
int a; // defines a
extern const int c = 1; // defines c
int f(int x) { return x + a; } // defines f and defines x
struct S { int a; int b; }; // defines S, S::a, and S::b
struct X { // defines X
int x; // defines non-static data member x
static int y; // DECLARES static data member y
X(): x(0) { } // defines a constructor of X
};
int X::y = 1; // defines X::y
enum { up , down }; // defines up and down
namespace N { int d; } // defines N and N::d
namespace N1 = N; // defines N1
X anX; // defines anX
// all these are declarations
extern int a; // declares a
extern const int c; // declares c
int f(int); // declares f
struct S; // declares S
typedef int Int; // declares Int
extern X anotherX; // declares anotherX
using N::d; // declares N::d
// specific to C++11 - these are not from the standard
enum X : int; // declares X with int as the underlying type
using IntVector = std::vector<int>; // declares IntVector as an alias to std::vector<int>
static_assert(X::y == 1, "Oops!"); // declares a static_assert which can render the program ill-formed or have no effect like an empty declaration, depending on the result of expr
template <class T> class C; // declares template class C
; // declares nothing
Định nghĩa :
extern int a; // Declaration
int a; // Definition
a = 10 // Initialization
int b = 10; // Definition & Initialization
Định nghĩa liên kết biến với một loại và phân bổ bộ nhớ, trong khi khai báo chỉ xác định loại nhưng không phân bổ bộ nhớ. Khai báo hữu ích hơn khi bạn muốn tham chiếu biến trước khi định nghĩa.
* Đừng nhầm lẫn định nghĩa với khởi tạo. Cả hai đều khác nhau, khởi tạo mang lại giá trị cho biến. Xem ví dụ trên.
Sau đây là một số ví dụ về định nghĩa.
int a;
float b;
double c;
Bây giờ chức năng khai báo:
int fun(int a,int b);
Lưu ý dấu chấm phẩy ở cuối hàm để nó nói nó chỉ là một khai báo. Trình biên dịch biết rằng ở đâu đó trong chương trình chức năng đó sẽ được xác định với nguyên mẫu đó. Bây giờ nếu trình biên dịch có một hàm gọi một cái gì đó như thế này
int b=fun(x,y,z);
Trình biên dịch sẽ đưa ra một lỗi nói rằng không có chức năng đó. Bởi vì nó không có bất kỳ nguyên mẫu nào cho chức năng đó.
Lưu ý sự khác biệt giữa hai chương trình.
Chương trình 1
#include <stdio.h>
void print(int a)
{
printf("%d",a);
}
main()
{
print(5);
}
Trong đó, chức năng in được khai báo và định nghĩa là tốt. Vì chức năng gọi đến sau định nghĩa. Bây giờ xem chương trình tiếp theo.
Chương trình 2
#include <stdio.h>
void print(int a); // In this case this is essential
main()
{
print(5);
}
void print(int a)
{
printf("%d",a);
}
Đó là điều cần thiết bởi vì hàm gọi trước định nghĩa để trình biên dịch phải biết liệu có bất kỳ hàm nào như vậy không. Vì vậy, chúng tôi khai báo hàm sẽ thông báo cho trình biên dịch.
Định nghĩa :
Phần xác định hàm này được gọi là Định nghĩa. Nó nói phải làm gì bên trong chức năng.
void print(int a)
{
printf("%d",a);
}
int a; //declaration; a=10; //definition
Điều này là hoàn toàn sai. Khi nói về các đối tượng thời lượng lưu trữ tự động (các đối tượng được khai báo bên trong một định nghĩa hàm không được khai báo với một công cụ xác định lớp lưu trữ khác như extern), đây luôn là các định nghĩa.
Quy tắc của ngón tay cái:
Một khai báo cho trình biên dịch biết cách diễn giải dữ liệu của biến trong bộ nhớ. Điều này là cần thiết cho mọi truy cập.
Một định nghĩa dự trữ bộ nhớ để làm cho biến hiện có. Điều này phải xảy ra chính xác một lần trước khi truy cập đầu tiên.
Để hiểu các danh từ, hãy tập trung vào các động từ trước.
tuyên bố - công bố chính thức; tuyên bố
định nghĩa - để hiển thị hoặc mô tả (ai đó hoặc một cái gì đó) rõ ràng và đầy đủ
Vì vậy, khi bạn tuyên bố một cái gì đó, bạn chỉ cần nói nó là gì .
// declaration
int sum(int, int);
Dòng này khai báo một hàm C được gọi sum
có hai đối số kiểu int
và trả về một int
. Tuy nhiên, bạn chưa thể sử dụng nó.
Khi bạn cung cấp cách nó thực sự hoạt động , đó là định nghĩa của nó.
// definition
int sum(int x, int y)
{
return x + y;
}
Để hiểu sự khác biệt giữa khai báo và định nghĩa, chúng ta cần xem mã lắp ráp:
uint8_t ui8 = 5; | movb $0x5,-0x45(%rbp)
int i = 5; | movl $0x5,-0x3c(%rbp)
uint32_t ui32 = 5; | movl $0x5,-0x38(%rbp)
uint64_t ui64 = 5; | movq $0x5,-0x10(%rbp)
double doub = 5; | movsd 0x328(%rip),%xmm0 # 0x400a20
movsd %xmm0,-0x8(%rbp)
và đây chỉ là định nghĩa:
ui8 = 5; | movb $0x5,-0x45(%rbp)
i = 5; | movl $0x5,-0x3c(%rbp)
ui32 = 5; | movl $0x5,-0x38(%rbp)
ui64 = 5; | movq $0x5,-0x10(%rbp)
doub = 5; | movsd 0x328(%rip),%xmm0 # 0x400a20
movsd %xmm0,-0x8(%rbp)
Như bạn có thể thấy không có gì thay đổi.
Khai báo khác với định nghĩa vì nó cung cấp thông tin chỉ được sử dụng bởi trình biên dịch. Ví dụ uint8_t báo cho trình biên dịch sử dụng hàm asm Movb.
Xem đó:
uint def; | no instructions
printf("some stuff..."); | [...] callq 0x400450 <printf@plt>
def=5; | movb $0x5,-0x45(%rbp)
Tuyên bố không có một hướng dẫn tương đương vì nó không phải là một cái gì đó để được thực thi.
Hơn nữa khai báo cho trình biên dịch phạm vi của biến.
Chúng ta có thể nói rằng khai báo là một thông tin được sử dụng bởi trình biên dịch để thiết lập việc sử dụng đúng biến và trong bao lâu một số bộ nhớ thuộc về biến nhất định.
Bạn không thể nói theo các thuật ngữ chung nhất có thể, rằng một tuyên bố là một định danh trong đó không có lưu trữ được phân bổ và một định nghĩa thực sự phân bổ lưu trữ từ một định danh khai báo?
Một suy nghĩ thú vị - một mẫu không thể phân bổ lưu trữ cho đến khi lớp hoặc hàm được liên kết với thông tin loại. Vì vậy, định danh mẫu là một tuyên bố hoặc định nghĩa? Nó phải là một khai báo vì không có lưu trữ nào được phân bổ và bạn chỉ đơn giản là 'tạo mẫu' cho lớp hoặc hàm mẫu.
template<class T> struct foo;
là một khai báo mẫu , và đây cũng là một template<class T> void f();
. Các định nghĩa mẫu phản ánh các định nghĩa lớp / hàm theo cùng một cách. (Lưu ý rằng tên mẫu không phải là tên loại hoặc tên hàm . Một nơi bạn có thể thấy đây là khi bạn không thể chuyển mẫu dưới dạng tham số loại của mẫu khác. Nếu bạn muốn truyền mẫu thay vì loại, bạn cần tham số mẫu mẫu. )
Tìm câu trả lời tương tự ở đây: Câu hỏi phỏng vấn kỹ thuật trong C .
Một tuyên bố cung cấp một tên cho chương trình; một định nghĩa cung cấp một mô tả duy nhất về một thực thể (ví dụ như loại, thể hiện và chức năng) trong chương trình. Tuyên bố có thể được lặp đi lặp lại trong một phạm vi nhất định, nó giới thiệu một tên trong một phạm vi nhất định.
Một tuyên bố là một định nghĩa trừ khi:
Một định nghĩa là một tuyên bố trừ khi:
Theo hướng dẫn sử dụng thư viện GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
Trong C, một khai báo chỉ cung cấp thông tin rằng một hàm hoặc biến tồn tại và đưa ra kiểu của nó. Đối với một khai báo hàm, thông tin về các loại đối số của nó cũng có thể được cung cấp. Mục đích của khai báo là cho phép trình biên dịch xử lý chính xác các tham chiếu đến các biến và hàm được khai báo. Một định nghĩa, mặt khác, thực sự phân bổ lưu trữ cho một biến hoặc cho biết chức năng làm gì.
Khái niệm Tuyên bố và Định nghĩa sẽ hình thành một cạm bẫy khi bạn đang sử dụng lớp lưu trữ bên ngoài vì định nghĩa của bạn sẽ ở một số vị trí khác và bạn đang khai báo biến trong tệp mã địa phương (trang). Một điểm khác biệt giữa C và C ++ là trong C, các khai báo được thực hiện bình thường ở đầu một hàm hoặc trang mã. Trong C ++ thì không như vậy. Bạn có thể tuyên bố tại một nơi bạn chọn.
Ví dụ yêu thích của tôi là "int Num = 5" ở đây biến của bạn là 1. được định nghĩa là int 2. được khai báo là Num và 3. được khởi tạo với giá trị là năm. Chúng tôi
Một lớp hoặc struct cho phép bạn thay đổi cách xác định các đối tượng khi nó được sử dụng sau này. Ví dụ
Khi chúng ta học lập trình, hai thuật ngữ này thường bị nhầm lẫn bởi vì chúng ta thường làm cả hai cùng một lúc.
Các giai đoạn của một thế hệ thực thi:
(1) bộ xử lý trước -> (2) trình biên dịch / trình biên dịch -> (3) trình liên kết
Trong giai đoạn 2 (trình dịch / trình biên dịch), các câu lệnh khai báo trong mã của chúng tôi cho trình biên dịch biết rằng những thứ này chúng ta sẽ sử dụng trong tương lai và bạn có thể tìm thấy định nghĩa sau, nghĩa là:
người dịch chắc chắn rằng: cái gì là cái gì? có nghĩa là khai báo
và (3) giai đoạn (trình liên kết) cần định nghĩa để ràng buộc mọi thứ
Linker đảm bảo rằng: ở đâu là gì? có nghĩa là định nghĩa
Có một số định nghĩa rất rõ ràng được rắc khắp K & R (phiên bản 2); nó giúp đặt chúng ở một nơi và đọc chúng như một:
"Định nghĩa" chỉ nơi lưu trữ biến được tạo hoặc chỉ định lưu trữ; "Khai báo" chỉ những nơi mà bản chất của biến được nêu nhưng không có lưu trữ được phân bổ. [p. 33]
...
Điều quan trọng là phải phân biệt giữa khai báo một biến ngoài và định nghĩa của nó . Một khai báo công bố các thuộc tính của một biến (chủ yếu là kiểu của nó); một định nghĩa cũng khiến lưu trữ được đặt sang một bên. Nếu các dòng
int sp; double val[MAXVAL]
xuất hiện bên ngoài bất kỳ chức năng nào, chúng xác định các biến bên ngoài
sp
vàval
, khiến cho việc lưu trữ được đặt sang một bên và cũng đóng vai trò là khai báo cho phần còn lại của tệp nguồn đó.Mặt khác, các dòng
extern int sp; extern double val[];
khai báo cho phần còn lại của tệp nguồn
sp
là mộtint
và đóval
là mộtdouble
mảng (có kích thước được xác định ở nơi khác), nhưng chúng không tạo ra các biến hoặc lưu trữ dự trữ cho chúng.Chỉ có một định nghĩa về một biến ngoài trong số tất cả các tệp tạo nên chương trình nguồn. ... Kích thước mảng phải được chỉ định với định nghĩa, nhưng là tùy chọn với
extern
khai báo. [Trang. 80-81]...
Tuyên bố xác định giải thích được đưa ra cho mỗi định danh; họ không nhất thiết phải lưu trữ lưu trữ liên quan đến định danh. Tuyên bố lưu trữ dự trữ được gọi là định nghĩa . [p. 210]
Khai báo nghĩa là đặt tên và loại cho một biến (trong trường hợp khai báo biến), vd:
int i;
hoặc đặt tên, kiểu trả về và loại tham số cho một hàm không có phần thân (trong trường hợp khai báo hàm), ví dụ:
int max(int, int);
trong khi định nghĩa có nghĩa là gán giá trị cho một biến (trong trường hợp định nghĩa biến), vd:
i = 20;
hoặc cung cấp / thêm phần thân (chức năng) cho một hàm được gọi là định nghĩa hàm, ví dụ:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
nhiều thời gian khai báo và định nghĩa có thể được thực hiện cùng nhau như:
int i=20;
và:
int max(int a, int b)
{
if(a>b) return a;
return b;
}
Trong các trường hợp trên, chúng tôi xác định và khai báo biến i
và function max()
.
int x;