Typedef và #define có giống nhau trong c không?


Câu trả lời:


122

Không.

#definelà một mã thông báo tiền xử lý: chính trình biên dịch sẽ không bao giờ nhìn thấy nó.
typedeflà một mã thông báo của trình biên dịch: bộ tiền xử lý không quan tâm đến nó.

Bạn có thể sử dụng cách này hoặc cách khác để đạt được hiệu quả tương tự, nhưng tốt hơn là sử dụng loại phù hợp với nhu cầu của bạn

#define MY_TYPE int
typedef int My_Type;

Khi mọi thứ trở nên "xơ xác", sử dụng công cụ thích hợp sẽ làm cho nó trở nên đúng đắn

#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);

void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */

3
Sau typedef stdfx, các đối tượng hợp lệ của kiểu đó là con trỏ đến các hàm nhận int và không trả về giá trị.
pmg

1
Tại sao lỗi #define trong casec của con trỏ hàm làm đối số?
Allahjane

2
@Allahjane: mở rộng trở thành void fx_def(void (*)(int) fx);; khai báo đúng là void fx_def(void (*fx)(int));.
pmg

5
Chức năng gợi ý là doable với macro, chỉ khi bạn đã sẵn sàng từ bỏ cú pháp: #define FX_TYPE(f) void (*f)(int). Sau đó, bạn sẽ khai báo hàm của mình là:void fx_def(FX_TYPE(fx));
plafer

229

typedeftuân theo các quy tắc xác định phạm vi giống như các biến, trong khi definevẫn hợp lệ cho đến khi kết thúc đơn vị biên dịch (hoặc cho đến khi khớp undef).

Ngoài ra, một số điều có thể được thực hiện với những typedefđiều không thể được thực hiện với define.
Ví dụ:

typedef int* int_p1;
int_p1 a, b, c;  // a, b, c are all int pointers

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer, because int_p2
                 // is replaced with int*, producing: int* a, b, c
                 // which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c;  // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp;  // func_p is a pointer to a function that
            // takes an int and returns an int

23

Không, họ không giống nhau. Ví dụ:

#define INTPTR int*
...
INTPTR a, b;

Sau khi xử lý trước, dòng đó mở rộng thành

int* a, b;

Hy vọng rằng bạn nhìn thấy vấn đề; chỉ asẽ có loại int *; bsẽ được khai báo là đơn giản int(vì *được liên kết với bộ khai báo, không phải từ chỉ định kiểu).

Đối lập điều đó với

typedef int *INTPTR;
...
INTPTR a, b;

Trong trường hợp này, cả hai absẽ có loại int *.

Có toàn bộ các lớp typedef không thể được mô phỏng bằng macro bộ xử lý trước, chẳng hạn như con trỏ đến các hàm hoặc mảng:

typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20]; 
...
CALLBACK aCallbackFunc;        // aCallbackFunc is a pointer to a function 
                               // returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
                               // returning a pointer to a 20-element array
                               // of pointers to int

Hãy thử làm điều đó với macro bộ xử lý trước.


13

#define xác định macro.
typedef xác định các loại.

Bây giờ nói rằng, đây là một vài khác biệt:

Với #define, bạn có thể xác định các hằng số có thể được sử dụng trong thời gian biên dịch. Các hằng số có thể được sử dụng với #ifdef để kiểm tra cách mã được biên dịch và chuyên biệt hóa mã nhất định theo các tham số biên dịch.
Bạn cũng có thể sử dụng #define để khai báo các hàm Macro thu nhỏ tìm và thay thế .

typedef có thể được sử dụng để cung cấp bí danh cho các loại (bạn cũng có thể làm với #define ), nhưng sẽ an toàn hơn vì tính chất tìm và thay thế của hằng #define .
Bên cạnh đó, bạn có thể sử dụng khai báo chuyển tiếp với typedef cho phép bạn khai báo một kiểu sẽ được sử dụng, nhưng chưa được liên kết với tệp bạn đang viết.


ý của bạn khi tìm và thay thế tính chất của #define là gì? , Cảm ơn bạn
Mohamed El Shenawy

1
Nó có nghĩa là trước khi biên dịch, tiền xử lý sẽ tìm thấy tất cả các macro và thay thế chúng với cú pháp ban đầu của họ
Hoàng tử Vijay Pratap

"typedef có thể được sử dụng để cung cấp bí danh cho các loại" Điều này giải thích mục đích cho tôi, cảm ơn.
Dave Voyles

8

Macro tiền xử lý (" #defines") là một công cụ thay thế từ vựng được gọi là "tìm kiếm và thay thế". Họ hoàn toàn không hiểu về ngôn ngữ lập trình và không hiểu bạn đang cố gắng làm gì. Bạn có thể coi chúng như một thợ sao chép / dán được tôn vinh - đôi khi điều đó hữu ích, nhưng bạn nên sử dụng nó một cách cẩn thận.

Typedefs là một tính năng ngôn ngữ C cho phép bạn tạo bí danh cho các loại. Điều này cực kỳ hữu ích để làm cho các kiểu phức hợp phức tạp (như cấu trúc và con trỏ hàm) có thể đọc và xử lý được (trong C ++ thậm chí có những trường hợp bạn phải gõ một kiểu).

Đối với (3): Bạn nên luôn thích các tính năng ngôn ngữ hơn các macro tiền xử lý khi có thể! Vì vậy, hãy luôn sử dụng typedef cho các kiểu và các giá trị không đổi cho các hằng số. Bằng cách đó, trình biên dịch thực sự có thể tương tác với bạn một cách có ý nghĩa. Hãy nhớ rằng trình biên dịch là bạn của bạn, vì vậy bạn nên nói với nó càng nhiều càng tốt. Macro tiền xử lý làm ngược lại hoàn toàn bằng cách ẩn ngữ nghĩa của bạn khỏi trình biên dịch.


Bạn có thể cho một ví dụ trong C ++ nơi bạn phải gõ một kiểu không? Tôi chỉ tò mò về điều đó.
jyz

@jyzuz: Có điều gì đó nếu bạn muốn một hàm thành viên trả về một mảng con trỏ hàm hoặc tương tự như vậy - nếu bạn cố gắng đánh vần kiểu, GCC thực sự nói rằng "bạn phải sử dụng typedef".
Kerrek SB

4

Chúng rất khác nhau, mặc dù chúng thường được sử dụng để triển khai các kiểu dữ liệu tùy chỉnh (đó là những gì tôi đang giả định câu hỏi này là tất cả về).

Như pmg đã đề cập, #defineđược xử lý bởi bộ xử lý trước (giống như hoạt động cắt và dán) trước khi trình biên dịch nhìn thấy mã và typedefđược trình biên dịch giải thích.

Một trong những điểm khác biệt chính (ít nhất là khi nói đến việc xác định kiểu dữ liệu) là typedefcho phép kiểm tra kiểu cụ thể hơn. Ví dụ,

#define defType int
typedef int tdType

defType x;
tdType y;

Ở đây, trình biên dịch xem biến x là một int, nhưng biến y là một kiểu dữ liệu được gọi là 'tdType' có cùng kích thước với một int. Nếu bạn đã viết một hàm nhận tham số kiểu defType, trình gọi có thể chuyển một int bình thường và trình biên dịch sẽ không biết sự khác biệt. Nếu thay vào đó, hàm nhận một tham số kiểu tdType, trình biên dịch sẽ đảm bảo rằng một biến có kiểu thích hợp được sử dụng trong các lần gọi hàm.

Ngoài ra, một số trình gỡ lỗi có khả năng xử lý typedefs, điều này có thể hữu ích hơn nhiều so với việc có tất cả các kiểu tùy chỉnh được liệt kê là kiểu nguyên thủy cơ bản của chúng (như nó sẽ như vậy nếu #defineđược sử dụng thay thế).


2

Không.
Typedef là một từ khóa C tạo bí danh cho một loại.
#define là một hướng dẫn xử lý trước, tạo sự kiện thay thế văn bản trước khi biên dịch. Khi trình biên dịch nhận được mã, từ "#defined" ban đầu không còn ở đó nữa. #define chủ yếu được sử dụng cho macro và hằng số toàn cục.


2
Việc sử dụng thuật ngữ "con trỏ" có thể dẫn đến một số nhầm lẫn ở đây.

Đã đồng ý. Đó là lý do tại sao tôi quay lại và thêm một liên kết đến typdef trên MSDN - đề phòng trong tương lai có ai đó sẽ sử dụng câu hỏi này để tìm typedef là gì. Nhưng có lẽ tôi nên thay đổi từ đó ...
Traveling Tech Guy

2

AFAIK, không.

typedefgiúp bạn thiết lập "bí danh" cho kiểu dữ liệu hiện có. Ví dụ. typedef char chr;

#definelà một chỉ thị tiền xử lý được sử dụng để xác định macro hoặc thay thế mẫu chung. Ví dụ. #define MAX 100, thay thế tất cả các lần xuất hiện MAXvới 100


0

Như đã đề cập ở trên, có một sự khác biệt chính giữa #definetypedef và typedef. Cách đúng đắn để nghĩ về điều đó là xem typedef là một kiểu "được đóng gói" hoàn chỉnh. Nó có nghĩa là bạn không thể thêm vào nó sau khi bạn đã khai báo nó.

Bạn có thể mở rộng tên kiểu macro với các từ chỉ định kiểu khác, nhưng không phải tên kiểu typedef'd:

#define fruit int
unsigned fruit i;   // works fine

typedef int fruit;
unsigned fruit i;   // illegal

Ngoài ra, tên typedef'd cung cấp kiểu cho mọi người khai báo trong một khai báo.

#define fruit int *
fruit apple, banana;

Sau khi mở rộng macro, dòng thứ hai trở thành:

int *apple, banana;

Apple là một con trỏ đến một int, trong khi banana là một int. Trong sự so sánh. một typedef như thế này:

typedef char *fruit;
fruit apple, banana;

tuyên bố cả táo và chuối giống nhau. Tên ở mặt trước khác nhau, nhưng cả hai đều là con trỏ đến một ký tự.


-1

Như mọi người đã nói ở trên, chúng không giống nhau. Hầu hết các câu trả lời chỉ ra typedeflà có lợi hơn #define. Nhưng hãy để tôi đặt một điểm cộng là #define:
khi mã của bạn cực kỳ lớn, nằm rải rác trên nhiều tệp, thì tốt hơn nên sử dụng #define; nó giúp dễ đọc - bạn có thể đơn giản xử lý trước tất cả mã để xem định nghĩa kiểu thực tế của một biến tại vị trí của chính nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.