Trong C cho biết kết quả biên dịch thực hiện đoạn chương trình sau

Hầu hết sau khi chúng ta sau khi viết xong một chương trình và chạy chúng bằng trình biên dịch, ta chỉ quan tâm đến việc chương trình của mình đúng hay sai chứ chẳng mấy khi quan tâm đến việc chương trình đó được biên dịch như thế nào?

Biên dịch chương trình là gì?

Quy trình dịch là quá trình chuyển đổi từ ngôn ngữ bậc cao sang ngôn ngữ đích (ngôn ngữ máy) để máy tính có thể hiểu và thực thi. Ngôn ngữ lập trình C++ là một ngôn ngữ dạng biên dịch. Chương trình được viết bằng C++ muốn chạy được trên máy tính phải trải qua một quá trình biên dịch để chuyển đổi từ dạng mã nguồn sang chương trình dạng mã thực thi. Quá trình được chia ra làm 4 giai đoạn chính:

Trong C cho biết kết quả biên dịch thực hiện đoạn chương trình sau

1. Preprocessing (tiền xử lý)

Bộ tiền xử lý có nhiệm vụ thực hiện:

  • Nhận mã nguồn
  • Xóa bỏ tất cả chú thích, comments của chương trình
  • Chỉ thị tiền xử lý (bắt đầu bằng #) cũng được xử lý

Chúng ta có thể bắt lỗi ngay ở giai đoạn này với việc sử dụng một cách hợp lý các chỉ thị #if  #error. Bằng cách sử dụng option -E của trình biên dịch như bên dưới, chúng ta có thể dừng quá trình biên dịch ngay ở giai đoạn tiền xử lý nếu có lỗi ở giai đoạn này.

Ví dụ: chỉ thị #include cho phép ghép thêm mã chương trình của một tệp tiêu để vào mã nguồn cần dịch. Các hằng số được định nghĩa bằng #define sẽ được thay thế bằng giá trị cụ thể tại mỗi nơi sử dụng trong chương trình.

Trong C cho biết kết quả biên dịch thực hiện đoạn chương trình sau

Sau khi thực hiện tiền xử lý

Trong C cho biết kết quả biên dịch thực hiện đoạn chương trình sau

Ta có thể thấy các hằng số được đinh nghĩa bằng #define đã được thay thế bằng các giá trị cụ thể

2. Compilation (biên dịch)

Bước biên dịch được thực hiện trên mỗi output của bộ tiền xử lý. Trình biên dịch phân tích mã nguồn C++ thuần túy (bây giờ không có bất kỳ chỉ thị tiền xử lý nào) và chuyển đổi nó assembly code. Ở giai đoạn này, trình biên dịch sẽ bắt các lỗi về kiểu dữ liệu, phân tích (syntax) cú pháp đồng thời có thể thực hiện tối ưu tự động source code để chương trình hoạt động hiệu quả hơn. Nếu có lỗi xảy ra trình biên dịch sẽ thông báo và chúng ta phải sửa lại code để xử lý các lỗi đó và thực hiện biên dịch lại.

Sau khi biên dịch ngon lành ở bước này, compiler sẽ gọi đến một cái back-end bên dưới gọi là assembler để convert tiếp assembly code thành các object code files chứa machine code (mã máy).

Quá trình này sẽ biên dịch các tệp tin .c/.cpp sang tệp tin object .s

Trong C cho biết kết quả biên dịch thực hiện đoạn chương trình sau

3. Assembling

Ở bước này thì assembler sẽ chuyển đổi các assembly code trong các assembler files thành mã máy (machine code – là mã mà CPU có thể hiểu được) trong các object code files. Lưu ý assembler phụ thuộc vào kiến trúc của CPU (x86, PowerPC, ARM,…) nên các kiến trúc CPU khác nhau thì sẽ có các assembler khác nhau. Trên hệ thống UNIX, các object code files có hậu tố .o (.OBJ trên Windows). Các object code files chứa code đã được biên dịch (ở dạng nhị phân) của các symbols (có hiểu đơn giản symbols ở đây là các hàm, các biến) định nghĩa trong file source đầu vào. Symbols trong các object code files được tham chiếu đến bằng tên.

Nói dễ hiểu thì ở giai đoạn này sẽ dịch chương trình thành mã máy 0, 1 và sinh ra tệp mã máy .o

4. Linker (Trình liên kết)

Giai đoạn này sẽ tạo thành chương trình đích duy nhất của quá trình biên dịch từ các object code files  assembler đã tạo ra ở bước trước đó. Đầu ra này có thể là thư viện shared (or dynamic) library hoặc file chaỵ (executable file).

Nó liên kết tất cả các object code files bằng cách thay thế các tham chiếu đến các symbols bằng các địa chỉ chính xác. Mỗi symbol này có thể được định nghĩa trong các object code files khác hoặc trong các thư viện. Nếu chúng được định nghĩa trong các thư viện khác với thư viện chuẩn, bạn cần phải khai báo rõ với linker về chúng (điều này được thực hiện thông qua các config build).

Ở giai đoạn này, các lỗi phổ biến nhất là thiếu định nghĩa hoặc định nghĩa trùng lặp.

  • Thiếu định nghĩa : Điều này có nghĩa là các định nghĩa không tồn tại (các class, các hàm không được implement) hoặc object code files hoặc thư viện nơi chúng cư trú không được cung cấp cho trình linker biết.
  • Trùng lặp: cùng một symbol được định nghĩa trong hai hoặc nhiều object code files hoặc thư viện khác nhau.
  • Chương trình chính không có hàm main().

Tạm kết

Hi vọng qua bài viết bạn có thể hiểu được quá trình biên dịch diễn ra như thế nào. Khi có thể hiểu được quá trình biên dịch ta có thể dễ dàng biết lỗi từ bước nào để fix.

Nguồn tham khảo: cppdeveloper.com

  • Câu hỏi:

    Cho đoạn chương trình:

    Begin

    a := 100;

    b := 30;

    x := a div b ;

    Write(x);

    End.

    Cho biết kết quả sau khi thực hiện lệnh :

    Lời giải tham khảo:

    Đáp án đúng: C

    Ta có a := 100;  gán cho a giá trị là 100

              b := 30 ;  gán cho b giá trị là 30

              x := a div b =100 div 30 =3 ( div là phép lấy nguyên)

    Đáp án: C

    Hãy trả lời câu hỏi trước khi xem đáp án và lời giải

Câu hỏi này thuộc đề thi trắc nghiệm dưới đây, bấm vào Bắt đầu thi để làm toàn bài

Câu hỏi trắc nghiệm. Môn thi: Lập trình hướng đối tượng Câu 1:Ký tự kết thúc chuỗi trong C++'.' ' ''\0' '\n'Câu 2:Lệnh nào sau đây dùng để nhập dữ liệu cho biến chuỗi ký tự tên là x từ bàn phím (nhập tối đa 100 ký tự) ?cin.getline(x, 100, '\n'); cin.getline(100, x, '\n');readline(x, 100, '\n'); read(x);Câu 3:Mục đích xây dựng lớp (class) trong phương pháp lập trình hướng đối tượng là để: Đóng gói dữ liệu (data encapsulation) Tạo cơ chế mô hình hóa các đối tượng trong thế giới thực.Sử dụng lại các lớp (reuse) Tất cả đều đúngCâu 4:Giới hạn truy xuất nào không có trong các lớp của C++hidden protectedprivate publicCâu 5:Hàm destructor phải trả về giá trị gì ? Một đối tượng của class Một con trỏ (pointer) trỏ đến class.Một giá trị cho biết class có được hủy đúng hay không.Không trả về giá trị nào cả.Câu 6:Khai báo class nào sau đây là hợp lệ class A { int x; }; class B { } public class A { } object A { int x; };Câu 7:Hàm mà bất kỳ classs nào cũng có:Không có hàm nào cả. ConstructorDestructor Constructor và DestructorCâu 8:Khi khai báo lớp trong C++, hành vi của đối tượng được khai báo như là :Không khai báo trong class Hàm hay phương thứcBiến hay thuộc tính Tên lớpCâu 9:Những phát biểu nào sau đây là đúng khi nói về lớp:Một đối tượng là một thể hiện (instance) cụ thể của một lớp.Lớp định nghĩa các thuộc tính và các phương thức chung cho tất cả các đối tượng của cùng một loại nào đó. Một lớp là một thiết kế hay mẫu cho các đối tượng cùng kiểu Tất cả đều đúngCâu 10:Kết quả biên dịch – thực thi đoạn chương trình sau: class Test {};void main() {Test t;}Lỗi thực thi. Lỗi biên dịch.Chương trình thực thi mà không xuất ra gì hết. Chương trình chạy vô tậnCâu 11:Mức độ 1 Không xáo trộn câuKết quả biên dịch – thực thi chương trình sau:class Test {public: int n;private: void Display(){ cout<<n; }public: Test(){ n=5; }};void main() {Test t;t.Display();}Lỗi thực thi Lỗi biên dịch.Chương trình thực thi xuất ra màn hình: 5. Chương trình thực thi mà không xuất gì ra màn hình.Câu 12:Mức độ 2 Không xáo trộn câuKết quả biên dịch - thực thi chương trình sau:class ABC {int n;public: ABC(int x){n=x; } void Print(){ cout<<n; }};void main() {ABC t;t.Print();}Lỗi thực thi Lỗi biên dịch.Chương trình thực thi xuất ra màn hình một số âm.Chương trình thực thi mà không xuất gì ra màn hình.Câu 13:Mức độ 0 Không xáo trộn câuKết quả biên dịch – thực thi chương trình sau: class Point {int xVal, yVal;public:Point(int x = 0, int y = 0){xVal = x ; yVal = y ;}void Print(){cout<<" ("<<xVal <<","<<yVal<<" )";}};void main() {Point pt(5);pt.Print();}Lỗi do khởi tạo đối tượng không đúng Hiển thị trên màn hình (0,5)Hiển thị trên màn hình (5,5) Hiển thị trên màn hình (5,0)Câu 14:Mức độ 1 Không xáo trộn câuKết quả biên dịch - thực thi chương trình sau: class Point {int xVal, yVal;public:Point(int x = 0, int y = 0){xVal = x ; yVal = y ;cout<< "So nguyen " ;}Point(double x = 0, double y = 0){xVal = x ; yVal = y ;cout<< "So thuc " ;}void Print() ;};void Point :: Print(){ cout<< " ("<<xVal <<","<<yVal<<" )"; } void main() {Point pt(5.7);pt.Print();getch();}Hiển thị trên màn hình So thuc (5,0) Hiển thị trên màn hình So nguyen (5,5)Hiển thị trên màn hình So nguyen (5,0) Chương trình bi lỗi biên dịch.Câu 15:Mức độ 1 Không xáo trộn câuKết quả biên dịch - thực thi chương trình sau:class Point { int n; Point(int x){n = x ;}void Print(){cout<<n; }};void main() {Point pt(4);pt.Print();}Lỗi thực thi Lỗi biên dịch.Chương trình thực thi xuất ra màn hình : 4 Chương trình thực thi mà không xuất gì ra màn hình.Câu 16:Mức độ 2 Không xáo trộn câuKết quả biên dịch - thực thi chương trình sau:class Test {int t;public :Test(int t){ Test::t = t ; }void Print(){cout<<t; }};void main() {Test test(4);test.Test::Print();}Lỗi thực thi Lỗi biên dịch.Chương trình thực thi xuất ra màn hình : 4 Chương trình thực thi mà không xuất gì ra màn hình.Câu 17:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau Kết quả sẽ là : class AAA {int na;public :AAA(int a=0) {na = a ;}~AAA(){cout<< " "<<na ;}};void Func(AAA aaa){AAA *a1 = new AAA(3);delete a1;}void main() {AAA aaa(4); Func(aaa);}Xuất ra màn hình : 0 3 4 Xuất ra màn hình : 3 4 4Xuất ra màn hình : 3 3 4 Xuất ra màn hình : 3 4Câu 18:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là : class AAA {int na;public :AAA(int a=0) {na = a ;}~AAA(){cout<< " "<<na ;}};void Func(const AAA& aaa){AAA *a1 = new AAA(3);delete a1;}void main() {AAA aaa(4); Func(aaa);}Xuất ra màn hình : 0 3 4 Xuất ra màn hình : 3 4 4Xuất ra màn hình : 3 3 4 Xuất ra màn hình : 3 4Câu 19:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là:class Teacher {public:static int n;public : Teacher (){ cout<<" "<<n++ ; }};int Teacher::n = 0;void main() {Teacher t1;Teacher t2;Teacher t3;cout<<" "<<t1.n ;getch();}Xuất ra màn hình : 0 1 2 3 Xuất ra màn hình : 1 2 3 4Xuất ra màn hình : 0 1 2 2 Xuất ra màn hình : 1 2 3 1Câu 20:Mức độ 1 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là : class Employee {char ten[30];char ms[10];int tuoi;public :Employee (char te[], char m[], int tu):tuoi(tu){ strcpy(ten, te);strcpy(ms, m);}void Display(){cout<<"Ma so: "<<ms<<" Ten: "<<ten<<" Tuoi:"<<tuoi<<endl ;}};void main() {Employee e(" Nguyen Van A", "001",20); e.Display();}Lỗi biên dịch. Xuất hiện trên,màn hinh: “Ma so: 001 Ten: Nguyen Van A Tuoi: 20”Lỗi thực thi Không hiển thị gì trên màn hình.Câu 21:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là : class Base{public:Base(){ cout<<”Base class”<<endl; }};class Derive:Base{public: Derive(){ cout<<”Derive class”<<endl; }};void main(){Derive d;}Base class Derive class Derive class Base classBase class Derive classCâu 22:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class Base{public:Base(){} ~Base(){ cout<<”Base class”<<endl; }};class Derive:Base{public:Derive(){} ~Derive(){ cout<<”Derive class”<<endl; }};void main(){Derive d;}Base class Derive class Derive class Base classBase class Derive classCâu 23:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class Base{public:int xVal;Base(int x=0) : xVal(x){ cout<<”xVal = ”<<xVal<<endl; }};class Derive:Base{public: Derive(){xVal = 10;}void Print(){cout<<”xVal = ”<<xVal<<endl; }};void main(){Derive d;d.Print();}Màn hình xuất hiện: xVal = 0 xVal = 10 Màn hình xuất hiện: xVal = 0Màn hình xuất hiện: xVal = 10 Chương trình bị lỗiCâu 24:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class Base{protected:int xVal;public:Base(){ xVal = 5; }public:void Print(){ cout<<”xVal = ”<<xVal<<endl;}};class Derive:public Base{public:Derive(int x) { xVal = x;}};void main(){Derive d(10);d.Print(); }Màn hình xuất hiện: xVal = 5 xVal = 10 Màn hình xuất hiện: xVal = 5Màn hình xuất hiện: xVal = 10 Chương trình bị lỗi.Câu 25:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là : class Base{protected:int xVal;public: Base(){ xVal = 5; }public: void Print(){ cout<<”xVal = ”<<xVal<<endl;}};class Derive:protected Base{public: Derive(int x) { xVal = x; }};void main(){Derive d(10);d.Print();}Màn hình xuất hiện: xVal = 5 xVal = 10 Màn hình xuất hiện: xVal = 5Màn hình xuất hiện: xVal = 10 Chương trình bị lỗi.Câu 26:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là: class BaseA{ protected:int A;public:BaseA(){ A = 5; }void Print(){ cout<<”A = ”<<A<<endl; }};class BaseB { protected:int B;public:BaseB(){ B = 10; }void Print(){ cout<<”B = ”<<B<<endl; }};class Derive:public BaseA,public BaseB {}; void main(){Derive d();d.BaseA::Print(); }Chương trình bị lỗi. Màn hình xuất hiện: A = 5Màn hình xuất hiện: B = 10 Màn hình xuất hiện: A = 5 B = 10Câu 27:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là: class Point{private:int xVal, yVal; public: void Print(){cout<<"("<<xVal<<","<<yVal<<")";}Point(int x=0, int y=0):xVal(x),yVal(y){} Point(int x){Point::xVal = Point::yVal = x;}friend Point operator + (Point, Point);};Point operator + (Point p1, Point p2){return Point(p1.xVal+p2.xVal, p1.yVal+p2.yVal);}void main(){Point p1(3,4); Point p = p1+3; p.Print();}Lỗi biên dịch Lỗi thực thiKết quả là (6,7) Kết quả là (6,4)Câu 28:Mức độ 2 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class Point{ private: int xVal, yVal; public:void Print(){cout<<"("<<xVal<<","<<yVal<<")";}Point(int x, int y):xVal(x),yVal(y){ }Point(int x){Point::xVal = Point::yVal = x;}friend Point operator + (Point, Point);};Point operator + (Point p1, Point p2){return Point(p1.xVal+p2.xVal, p1.yVal+p2.yVal);}void main(){Point p1(3,4); Point p = p1+6; p.Print();system("pause");}Lỗi biên dịch Lỗi thực thiKết quả là (9,10) Kết quả là (9,4)Câu 29:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class Set{int n, size, *elems;public:Set(int s=0):size(s), n(0), elems(new int[s]) { for(int i=0; i<s; i++) elems[i] = i;}void Print(){for(int i=0; i<size; i++) cout<<" "<<elems[i];}Set Func(Set);~Set() {delete []elems;}Set Set::Func (Set s1 ){Set s = s1;return s;}void main(){Set s(10);Set s1= s.Func(s); s.Print();}Lỗi biên dịch Lỗi thực thiKết quả là : 0 1 2 3 4 5 6 7 8 9 Là một kết quả khácCâu 30:Mức độ 3 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là : class Test{public:Test(){cout<<" A ";}Test(const Test& t){ cout<<" B "; }void operator=(const Test&t){ cout<<" C "; }};void main(){Test t1;Test t2; t2 = t1;}Kết quả là : A A B Kết quả là : A A CKết quả là : A B C Là một kết quả khácCâu 31:Mức độ 4 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :class A{public:A(){cout<<" A ";}};class B{public:B(){cout<<" B ";}};void SinhLoi(int a){if(a>0) throw A(); throw B();}void main(){int n=-1;try{SinhLoi(n);}catch(A){ cout<<" C " ; }catch(B){ cout<<" D "; }}Kết quả là : B D Kết quả là : A DKết quả là : B C Kết quả là : A CCâu 32:Mức độ 4 Không xáo trộn câu1: template <class T> T max(T a, T b) {2: if (a > b) return a;3: return b;4: }5: float max (float fa, float fb) {6: if (fa - fb >0) return fa;7: return fb;8: }9: void main(){10: 11: cout<<max(a,b);12: }Khi thêm lệnh nào vào dòng 10 thì chương trình báo lỗi:float a = 5.0, b = 6.0 ; char a = ‘A’, b = ‘B’ ;float a = 5.0; int b = 6 ; int a = 5; int b = 6 ;Câu 33:Mức độ 4 Không xáo trộn câu1: template <class T, class U>2: void func (T a, U b){3: cout<<a<<b ;4: }5: void main(){6:7: func(a,b);8: }Thêm lệnh nào đúng nhất dưới đây mà khi thêm vào dòng 6 thì chương trình không báo lỗifloat a = 5.0, b = 6.0 ; char a = ‘A’ ; char *b = “Hello” ;float a = 5.0; int b = 6 ; Tất cả câu trênCâu 34:Mức độ 4 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là :template <class T> class Test {T x, y;public:Test(T a = 0, T b = 0) {x = b; y = a;}void display();}void point<T>::display() {cout<<"("<<x<<","<<y<<") ";}void main() {Test<int> ti(3,5); ti.display();Test<char> tc('a','b'); tc.display();}Kết quả là : (3, 5) (a, b) Chương trình bị lỗiKết quả là : (5, 3) (b, a) Một kết quả khácCâu 35:Mức độ 4 Không xáo trộn câuKhi thực thi đoạn chương trình sau kết quả sẽ là:template <class T, int n> class table{T data[n];public:table() { }T & operator[](int i){ return data[i]; }};void main(){int n = 2;table <int, n>t;t[0] =0; t[1] =1;cout<<t[0]<<" "<<t[1];}Lỗi biên dịch Lỗi thực thi0 1 Một kết quả khác