C3: Liệu Có Phải Là C++ Thế Hệ Mới, Nhẹ Nhàng và An Toàn Hơn?

Trong thế giới phát triển phần mềm không ngừng phát triển, ngôn ngữ lập trình đóng vai trò nền tảng. C++ đã thống trị trong nhiều thập kỷ, nhưng những chỉ trích ngày càng tăng về độ phức tạp, các vấn đề an toàn bộ nhớ và kích thước file thực thi đã mở đường cho các giải pháp thay thế mới. Một trong số đó là C3, một ngôn ngữ hứa hẹn mang lại sự đơn giản của C cùng với sức mạnh của C++.

Bối Cảnh Hiện Tại: C++ Đang Đối Mặt Với Những Thách Thức Nào?

C++ là một ngôn ngữ mạnh mẽ và linh hoạt, nhưng cũng không ít lần bị chỉ trích. Các vấn đề nổi bật bao gồm:

Những lời chỉ trích này, như dự đoán, đã không được Bjarne Stroustrup, người tạo ra C++, đón nhận một cách dễ dàng. Tuy nhiên, chúng đã thúc đẩy sự ra đời của các ngôn ngữ lập trình mới nhằm thay thế hoặc bổ sung cho C++.

Sự Trỗi Dậy Của Các Ngôn Ngữ Thay Thế

Để giải quyết những hạn chế của C++, nhiều ngôn ngữ lập trình mới đã xuất hiện. Một số được thiết kế để trở thành sự thay thế trực tiếp, trong khi số khác tập trung vào việc đơn giản hóa trải nghiệm lập trình và cung cấp các tính năng độc đáo.

  • Thay thế trực tiếp phổ biến: Các ứng cử viên hàng đầu bao gồm C#Java, cả hai đều cung cấp tính năng quản lý bộ nhớ tự động và môi trường phát triển mạnh mẽ.
  • Các ngôn ngữ hiện đại khác: Ngoài ra, nhiều ngôn ngữ khác đã nổi lên để giải quyết các vấn đề cụ thể của C++ và mang đến những cách tiếp cận mới. Các ví dụ đáng chú ý là Zig, V, và Rust, mỗi ngôn ngữ đều có những ưu điểm riêng về hiệu suất, an toàn và cú pháp.

C2 và C3: Hành Trình Hướng Tới Sự Đơn Giản Hóa

Trong bối cảnh tìm kiếm sự đơn giản hóa, Bas vd Berg đã tạo ra C2 vào năm 2013, một sự phát triển của ngôn ngữ lập trình C với mục tiêu loại bỏ sự phức tạp không cần thiết. C2 loại bỏ các file header .h truyền thống và các macro phức tạp, mang lại một cách tiếp cận trực tiếp và dễ hiểu hơn.

Tiếp nối tinh thần đó, ngôn ngữ lập trình C3 được xây dựng dựa trên nền tảng của C2. C3 không chỉ hướng tới mục tiêu tương tự là loại bỏ sự phức tạp, mà còn bổ sung thêm các khả năng làm cho nó gần hơn với C++. Đây chính là trọng tâm của bài viết này: khám phá C3 như một phiên bản “C++ nhẹ” tiềm năng.

C3 Thực Tế: Mã Nguồn Dễ Đọc và Dễ Hiểu

C3 được thiết kế để mang lại trải nghiệm lập trình trực quan, với cú pháp quen thuộc đối với những người đã từng làm việc với C hoặc C++, nhưng lại đơn giản hóa nhiều điểm phức tạp.

Chương Trình “Hello, World!” Với C3

Để bắt đầu, hãy xem chương trình “Hello, World!” trong C3:

import std::io;

fn void main()
{
    io::println("¡Hola, mundo!");
}

Để biên dịch và chạy, bạn có thể thực hiện như sau:

$ c3c compile holamundo.c3
$ ./holamundo
¡Hola, mundo!

Điểm khác biệt cú pháp so với C rất ít. Các hàm được thêm tiền tố fn để dễ dàng phân biệt với các cấu trúc khác. Thay vì các file header, C3 sử dụng các module thực sự được nhập bằng từ khóa import, giúp ý nghĩa và ngữ nghĩa của chương trình trở nên rõ ràng hơn nhiều.

Ví Dụ Nâng Cao: Tìm Bộ Ba Pytago Với C3

Để minh họa thêm về khả năng của C3, chúng ta sẽ xem xét một chương trình tìm kiếm các bộ ba Pytago (a, b, c) thỏa mãn a² + b² = c² từ các số ngẫu nhiên.

import std::io;
import std::time;
import std::core::string;
import std::collections::list;
import std::math::random;

struct Terna {
    ulong a;
    ulong b;
    ulong c;
}

fn bool Terna.chk(&self)
{
    ulong sqa = self.a * self.a;
    ulong sqb = self.b * self.b;
    ulong sqc = self.c * self.c;

    return ( sqc == ( sqa + sqb ) );
}

fn String Terna.str(&self)
{
    return string::tformat( "(%d, %d, %d)", self.a, self.b, self.c );
}

fn void main()
{
    random::Lcg128Random rand;
    List{ Terna } l;

    io::printn( "Ternas pitagóricas\nCalculando..." );

    l.push( { 3, 4, 5 } );

    ulong i;
    for(i = 0; i < 1_000_000_000; i++) {
        Terna t = { rand.next_long(), rand.next_long(), rand.next_long() };

        if ( t.chk() ) {
            l.push( t );
        }
    }

    io::printf( "%d ternas encontradas tras %d ciclos.\n", l.len(), i );

    foreach(Terna t: l) {
        io::printn( t.str() );
    }
}

Trong ví dụ này:

  • Chương trình tạo một cấu trúc Terna bao gồm ba số nguyên ulong (128 bit) không dấu.
  • Phương thức Terna.chk() kiểm tra tính hợp lệ của bộ ba Pytago (a² + b² = c²).
  • Phương thức Terna.str() trả về biểu diễn chuỗi của bộ ba.
  • Chúng ta sử dụng Lcg128Random từ module std::math::random để tạo số nguyên 128 bit ngẫu nhiên.
  • Vòng lặp thực hiện 1 tỷ lần, tạo các bộ ba ngẫu nhiên và thêm chúng vào một danh sách động (List{ Terna }) nếu chúng là bộ ba Pytago hợp lệ.

Đánh Giá Hiệu Suất và Kích Thước File Thực Thi

C3 không chỉ dễ hiểu mà còn mang lại hiệu suất ấn tượng, đặc biệt là về tốc độ biên dịch và tốc độ thực thi của chương trình.

Thử Nghiệm Hiệu Suất C3

Khi biên dịch và chạy chương trình tìm bộ ba Pytago:

$ c3c compile ternas_pitagoricas.c3
$ ./ternas_pitagoricas
Ternas pitagóricas
Calculando...
1 ternas encontradas tras 1000000000 ciclos.
(3, 4, 5)

Chương trình thực hiện một tỷ (1.000.000.000) vòng lặp trong khoảng 17 giây một cách nhất quán. Điều này bao gồm việc tạo một bộ ba, gọi phương thức chk() (liên quan đến tính toán toán học), và thêm vào danh sách nếu hợp lệ.

$ time ./ternas_pitagoricas
Ternas pitagóricas
Calculando...
1 ternas encontradas tras 1000000000 ciclos.
(3, 4, 5)
./ternas_pitagoricas  16,38s user 0,00s system 99% cpu 16,438 total

$ time ./ternas_pitagoricas
Ternas pitagóricas
Calculando...
1 ternas encontradas tras 1000000000 ciclos.
(3, 4, 5)
./ternas_pitagoricas  16,35s user 0,00s system 99% cpu 16,402 total

Về kích thước file thực thi, chương trình C3 tạo ra một file khoảng 700 KB:

$ ls -l ternas_pitagoricas
-rwxr-xr-x 1 baltasarq baltasarq 702640 mar 23 12:13 ternas_pitagoricas

So Sánh Với C++ Truyền Thống

Để có cái nhìn khách quan, chúng ta hãy so sánh với một phiên bản tương đương được viết bằng C++:

#include <string>
#include <list>
#include <cstdio>
#include <cstdlib> // For std::rand()

typedef unsigned long ulong; // Define ulong for C++ consistency

class Terna {
public:
    Terna(ulong a, ulong b, ulong c)
        :a(a), b(b), c(c)
    {}

    bool chk() const
    {
        ulong sqa = a * a;
        ulong sqb = b * b;
        ulong sqc = c * c;

        return ( sqc == ( sqa + sqb ) );
    }

    std::string str() const
    {
        return std::to_string( a )
                + ", " + std::to_string( b )
                + ", " + std::to_string( c );
    }
private:
    ulong a;
    ulong b;
    ulong c;
};

int main()
{
    std::list<Terna> l;

    printf( "Ternas pitagóricas\n" );

    ulong i = 0;
    l.push_back( Terna( 3, 4, 5 ) );

    for(; i < 1000000000ul; ++i) {
        // Note: std::rand() returns int, might not be suitable for 128-bit ulong
        Terna t( std::rand(), std::rand(), std::rand() ); 

        if ( t.chk() ) {
            l.push_back( t );
        }
    }

    printf( "%lu ternas encontradas tras %lu ciclos.\n", l.size(), i );

    for(Terna t: l) {
        printf( "%s\n", t.str().c_str() );
    }
}

Khi biên dịch và chạy chương trình C++:

$ g++ ternas_pitagoricas.cpp -o ternas_pitagoricas
$ time ./ternas_pitagoricas
Ternas pitagóricas
1 ternas encontradas tras 1000000000 ciclos.
3, 4, 5
./ternas_pitagoricas  17,20s user 0,00s system 99% cpu 17,270 total

Chúng ta cũng nhận được kết quả hiệu suất tương tự (khoảng 17 giây). Điều này không quá ngạc nhiên vì C3 cũng tận dụng backend LLVM, giống như nhiều trình biên dịch C++ hiện đại.

Tuy nhiên, sự khác biệt lớn nằm ở kích thước file thực thi và cách thức liên kết thư viện:

$ g++ ternas_pitagoricas.cpp -o ternas_pitagoricas    
$ ls -l ternas_pitagoricas
-rwxr-xr-x 1 baltasarq baltasarq 44320 mar 23 12:54 ternas_pitagoricas
$ ldd ternas_pitagoricas                                                
        linux-vdso.so.1 (0x00007faefdf04000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007faefdc00000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007faefdae2000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007faefdab5000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007faefd8c4000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007faefdf06000)

$ c3c compile ternas_pitagoricas.c3                                    
Program linked to executable './ternas_pitagoricas'.
$ ldd ternas_pitagoricas
        linux-vdso.so.1 (0x00007fad32973000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007fad32796000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007fad325a5000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fad32975000)

Mặc dù file thực thi C++ ban đầu có vẻ nhỏ hơn đáng kể (~44 KB so với ~700 KB của C3), điều quan trọng cần lưu ý là phiên bản C++ liên kết với thư viện chuẩn C++ (libstdc++.so.6), có kích thước lên tới khoảng 3 MB. C3, mặt khác, tạo ra một file thực thi độc lập (self-contained), chỉ liên kết với các thư viện hệ thống cơ bản như libm.so.6libc.so.6.

C3 Có Phải Là Tương Lai Của Lập Trình Hệ Thống?

C3 thể hiện một cách tiếp cận mới mẻ, kết hợp sự đơn giản của C với một số khả năng hướng đối tượng và module hóa của C++. Nó mang lại cú pháp trực quan, hiệu suất cao và khả năng tạo ra các file thực thi độc lập, gọn nhẹ. Đây là những đặc điểm rất hấp dẫn đối với phát triển hệ thống và các ứng dụng cần hiệu suất tối ưu.

Tuy nhiên, liệu C3 có trở thành người kế nhiệm chính thức của C++ hay một ngôn ngữ ổn định và được chấp nhận rộng rãi hay không, chỉ có thời gian mới có thể trả lời. Ngành công nghiệp phần mềm luôn thay đổi, và sự thành công của một ngôn ngữ phụ thuộc vào nhiều yếu tố như cộng đồng, hỗ trợ công cụ và khả năng thích ứng với các xu hướng công nghệ mới.

Với những ưu điểm nổi bật của mình, C3 chắc chắn là một ngôn ngữ đáng để khám phá và theo dõi đối với bất kỳ lập trình viên nào quan tâm đến hiệu suất, sự an toàn và đơn giản trong lập trình hệ thống.

Chỉ mục