C/C++

#define and typedef

Xin chào, hôm nay chúng ta sẽ tìm hiểu sự khác nhau giữa #definetypedef trong C/C++.


#define

Được dùng để tạo alias cho một symbolic name hoặc symbolic constant:

#define name alias

Sau khi được định nghĩa bởi #define, bất cứ sự xuất hiện nào của name trong source file sẽ được thay thế bởi alias (Tương tự như chức năng Find/Replace trong các Text Editor).

Chú ý: #define được xử lý bởi preprocessor.
Example 1 – #define

#include "stdio.h"
#define PI 3.14
#define WEBSITE "codelungtung.com"

void main() {
	printf("PI = %.2f\nMy website: %s\n", PI, WEBSITE);
}

Output:
PI = 3.14
My website: codelungtung.com


typedef

Cần nhấn mạnh rằng typedef không tạo ra một kiểu dữ liệu mới, nó chỉ đơn giản là tạo một cái tên mới cho một kiểu dữ liệu đã có sẵn.

Chú ý: typedef được xử lý bởi trình biên dịch, vì thế nó có thể thực hiện “textual substitution” tốt hơn so với khả năng của proprocessor.

Về mặt cú pháp, typedef được sử dụng tương tự như các từ khóa extern, static khi khai báo biến, tuy nhiên phần tên biến sẽ được thay thế bởi tên mới của kiểu dữ liệu.

extern dataType variableName;

typedef dataType newDataTypeName;

Example 2 – typedef

#include "stdio.h"

typedef char* String;
typedef int (*Ptr)(int, int);

int sum(int a, int b) {
	return a+b;
}

void doSomething(Ptr callback) {
	printf("Callback function: %d\n", callback(1,2));
}

void main() {
	String website = "codelungtung.com";
	int (*p1)(int, int) = sum;
	Ptr p2 = sum;
	printf("Website: %s\nSum 1 = %d\nSum 2 = %d\n", website, p1(10,20), p2(10,20));
	doSomething(sum);
}

Output:
Website: codelungtung.com
Sum 1 = 30
Sum 2 = 30
Callback function: 3

Giải thích:
– Dòng 3: chúng ta đặt tên mới cho kiểu dữ liệu char* (pointer trỏ đến chuỗi ký tự) là String;
– Dòng 4: chúng ta đặt tên mới cho kiểu dữ liệu int (*)(int, int) (pointer trỏ đến function có 2 tham số kiểu integer và trả về giá trị integer) là Ptr;
– Dòng 15, 16 và 17: áp dụng các tên dữ liệu mới này vào chương trình và so sánh với kiểu dữ liệu cũ.
– trong function doSomething(Ptr) chúng ta đã sử dụng Function Pointer để tạo Callback function.

Có 2 lý dó để sử dụng typedef:

  1. Giúp chương trình linh hoạt hơn. Khi thay đổi môi trường thực thi (thay đổi hệ điều hành, máy tính,…), nếu typedef được sử dụng cho kiểu dữ liệu mà phụ thuộc vào từng môi trường (chẳng hạn 32-bit, 64-bit), chúng ta chỉ cần chỉnh sửa lại typedef cho phù hợp;
  2. Giúp chương trình sáng sủa, rõ ràng hơn. Từ example 2 chúng ta thấy rằng kiểu dữ liệu Ptr dễ hiểu hơn rất nhiều so với kiểu int (*)(int, int).

THE DIFFERENCE BETWEEN #DEFINE AND TYDEDEF

  • #define được xử lý bởi preprocessor còn typedef được xử lý bởi compiler;
  • typedef tuân thủ theo scope rule (external, local variable) còn #define thì không;
  • #define phù hợp để tạo alias còn typedef phù hợp để tạo tên mới cho kiểu dữ liệu đã có sẵn.

Example 3: #define vs. typedef

#include "stdio.h"

#define DString char*
typedef char* TString;

void main() {
	DString a,b;
	TString c,d;
	printf("sizeof a: %d\nsizeof b: %d\nsizeof c: %d\nsizeof d: %d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));
}

Output:
sizeof a: 4
sizeof b: 1
sizeof c: 4
sizeof d: 4

Giải thích:
– Dòng 3: define alias char* cho DString;
– Dòng 4: tạo tên mới TString cho kiểu dữ liệu char*;
– Lý do biến sizeof(a) = 4 còn sizeof(b) = 1 là vì preprocessor đã Search-and-Replace DString với char*, như vậy dòng 7 tương đương với char* a,b;. Đến đây mọi thứ đã rõ ràng, chỉ có biến a được khai báo là kiểu pointer, biến b chỉ là kiểu char;
– Vì typedef được xử lý bởi compiler nên nó không chỉ đơn giản là Search-and-Replace như #define. TString được xem như là một kiểu dữ liệu, do đó ở dòng 8 khai báo TString sẽ được áp dụng cho cả c và d, vì vậy sizeof(c)và sizeof(d) cùng bằng 4.


Như vậy chúng ta đã tìm hiểu sự khác nhau cũng như ứng dụng của #define và typedef. Cảm ơn các bạn đã theo dõi bài viết.

Thân ái và quyết thắng.

Reference:
[1] typedef versus #define in C.
[2] C – typedef.
[3] The C Programming Language book.
[4] Function Pointer in C.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s