Câu trả lời ngắn gọn là, hầu hết các cấu trúc ngôn ngữ được hỗ trợ bởi C cũng được hỗ trợ bởi bộ vi xử lý của máy tính đích, do đó, mã C được biên dịch sẽ dịch rất độc đáo và hiệu quả sang ngôn ngữ hợp ngữ của bộ vi xử lý, do đó dẫn đến mã nhỏ hơn và dấu chân nhỏ hơn.
Câu trả lời dài hơn yêu cầu một chút kiến thức về hợp ngữ. Trong C, một câu lệnh như sau:
int myInt = 10;
sẽ dịch sang một cái gì đó như thế này trong assembly:
myInt dw 1
mov myInt,10
So sánh cái này với cái gì đó giống như C ++:
MyClass myClass;
myClass.set_myInt(10);
Mã hợp ngữ kết quả (tùy thuộc vào MyClass () lớn như thế nào), có thể thêm tới hàng trăm dòng hợp ngữ.
Nếu không thực sự tạo ra các chương trình bằng hợp ngữ, thì C thuần túy có lẽ là mã "mỏng nhất" và "chặt chẽ nhất" mà bạn có thể tạo một chương trình.
BIÊN TẬP
Với những nhận xét về câu trả lời của mình, tôi quyết định chạy một bài kiểm tra, chỉ vì sự tỉnh táo của bản thân. Tôi đã tạo một chương trình có tên "test.c", trông giống như sau:
#include <stdio.h>
void main()
{
int myInt=10;
printf("%d\n", myInt);
}
Tôi đã biên dịch nó thành assembly bằng gcc. Tôi đã sử dụng dòng lệnh sau để biên dịch nó:
gcc -S -O2 test.c
Đây là hợp ngữ kết quả:
.file "test.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d\n"
.section .text.unlikely,"ax",@progbits
.LCOLDB1:
.section .text.startup,"ax",@progbits
.LHOTB1:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB24:
.cfi_startproc
movl $10, %edx
movl $.LC0, %esi
movl $1, %edi
xorl %eax, %eax
jmp __printf_chk
.cfi_endproc
.LFE24:
.size main, .-main
.section .text.unlikely
.LCOLDE1:
.section .text.startup
.LHOTE1:
.ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
.section .note.GNU-stack,"",@progbits
Sau đó, tôi tạo một tệp có tên "test.cpp" đã xác định một lớp và xuất ra thứ giống như "test.c":
#include <iostream>
using namespace std;
class MyClass {
int myVar;
public:
void set_myVar(int);
int get_myVar(void);
};
void MyClass::set_myVar(int val)
{
myVar = val;
}
int MyClass::get_myVar(void)
{
return myVar;
}
int main()
{
MyClass myClass;
myClass.set_myVar(10);
cout << myClass.get_myVar() << endl;
return 0;
}
Tôi đã biên dịch nó theo cùng một cách, sử dụng lệnh này:
g++ -O2 -S test.cpp
Đây là tệp lắp ráp kết quả:
.file "test.cpp"
.section .text.unlikely,"ax",@progbits
.align 2
.LCOLDB0:
.text
.LHOTB0:
.align 2
.p2align 4,,15
.globl _ZN7MyClass9set_myVarEi
.type _ZN7MyClass9set_myVarEi, @function
_ZN7MyClass9set_myVarEi:
.LFB1047:
.cfi_startproc
movl %esi, (%rdi)
ret
.cfi_endproc
.LFE1047:
.size _ZN7MyClass9set_myVarEi, .-_ZN7MyClass9set_myVarEi
.section .text.unlikely
.LCOLDE0:
.text
.LHOTE0:
.section .text.unlikely
.align 2
.LCOLDB1:
.text
.LHOTB1:
.align 2
.p2align 4,,15
.globl _ZN7MyClass9get_myVarEv
.type _ZN7MyClass9get_myVarEv, @function
_ZN7MyClass9get_myVarEv:
.LFB1048:
.cfi_startproc
movl (%rdi), %eax
ret
.cfi_endproc
.LFE1048:
.size _ZN7MyClass9get_myVarEv, .-_ZN7MyClass9get_myVarEv
.section .text.unlikely
.LCOLDE1:
.text
.LHOTE1:
.section .text.unlikely
.LCOLDB2:
.section .text.startup,"ax",@progbits
.LHOTB2:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB1049:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $10, %esi
movl $_ZSt4cout, %edi
call _ZNSolsEi
movq %rax, %rdi
call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1049:
.size main, .-main
.section .text.unlikely
.LCOLDE2:
.section .text.startup
.LHOTE2:
.section .text.unlikely
.LCOLDB3:
.section .text.startup
.LHOTB3:
.p2align 4,,15
.type _GLOBAL__sub_I__ZN7MyClass9set_myVarEi, @function
_GLOBAL__sub_I__ZN7MyClass9set_myVarEi:
.LFB1056:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZStL8__ioinit, %edi
call _ZNSt8ios_base4InitC1Ev
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp __cxa_atexit
.cfi_endproc
.LFE1056:
.size _GLOBAL__sub_I__ZN7MyClass9set_myVarEi, .-_GLOBAL__sub_I__ZN7MyClass9set_myVarEi
.section .text.unlikely
.LCOLDE3:
.section .text.startup
.LHOTE3:
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I__ZN7MyClass9set_myVarEi
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.hidden __dso_handle
.ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
.section .note.GNU-stack,"",@progbits
Như bạn có thể thấy rõ ràng, tệp hợp ngữ kết quả lớn hơn nhiều trên tệp C ++ sau đó nằm trên tệp C. Ngay cả khi bạn cắt bỏ tất cả những thứ khác và chỉ so sánh C "main" với C ++ "main", thì vẫn còn rất nhiều thứ bổ sung.