C

#8
TIOBE#3
PYPL#4
GitHub#10
RedMonk#10
IEEESpectrum#9
JetBrains#10
プログラミング言語システムプログラミング手続き型低レベル組み込み

プログラミング言語

C言語(シー言語)

概要

C言語は、1972年にDennis Ritchieによって開発された手続き型プログラミング言語です。システムプログラミングの基礎となる言語として設計され、OS、組み込みシステム、高性能アプリケーションの開発で広く使用されています。多くの現代的なプログラミング言語の基礎となった影響力のある言語です。

詳細

C言語は、ハードウェアに近いレベルでの制御が可能でありながら、高水準言語としての使いやすさも兼ね備えています。ポインタによる直接的なメモリアクセス、効率的なコード生成、移植性の高さが特徴です。

Unix OSの開発に使用されたことから始まり、現在でもLinux kernel、組み込みシステム、デバイスドライバ、データベースエンジンなど、性能が重要視される分野で活用されています。C99、C11、C18と標準規格も継続的に更新されています。

書き方の例

Hello World

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

変数とデータ型

#include <stdio.h>

int main() {
    // 基本データ型
    int age = 25;
    float height = 175.5f;
    double weight = 70.5;
    char grade = 'A';
    char name[] = "太郎";
    
    // 配列
    int numbers[5] = {1, 2, 3, 4, 5};
    
    printf("名前: %s\n", name);
    printf("年齢: %d歳\n", age);
    printf("身長: %.1f cm\n", height);
    printf("体重: %.1f kg\n", weight);
    printf("成績: %c\n", grade);
    
    // 配列の表示
    printf("数値: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}

関数

#include <stdio.h>

// 関数プロトタイプ宣言
int add(int a, int b);
int factorial(int n);
void printArray(int arr[], int size);

int main() {
    int x = 5, y = 3;
    int sum = add(x, y);
    printf("%d + %d = %d\n", x, y, sum);
    
    int n = 5;
    printf("%d! = %d\n", n, factorial(n));
    
    int numbers[] = {10, 20, 30, 40, 50};
    printArray(numbers, 5);
    
    return 0;
}

// 二つの数を足す関数
int add(int a, int b) {
    return a + b;
}

// 階乗を計算する関数(再帰)
int factorial(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

// 配列を表示する関数
void printArray(int arr[], int size) {
    printf("配列: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

ポインタとメモリ管理

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    // 基本的なポインタ
    int value = 42;
    int *ptr = &value;
    
    printf("値: %d\n", value);
    printf("アドレス: %p\n", (void*)&value);
    printf("ポインタ経由の値: %d\n", *ptr);
    
    // 動的メモリ確保
    int *dynamicArray = (int*)malloc(5 * sizeof(int));
    if (dynamicArray == NULL) {
        printf("メモリ確保に失敗しました\n");
        return 1;
    }
    
    // 配列に値を設定
    for (int i = 0; i < 5; i++) {
        dynamicArray[i] = (i + 1) * 10;
    }
    
    // 配列の表示
    printf("動的配列: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", dynamicArray[i]);
    }
    printf("\n");
    
    // メモリ解放
    free(dynamicArray);
    
    // 文字列とポインタ
    char *str = (char*)malloc(50 * sizeof(char));
    if (str != NULL) {
        strcpy(str, "Hello, C Language!");
        printf("文字列: %s\n", str);
        free(str);
    }
    
    return 0;
}

構造体

#include <stdio.h>
#include <string.h>
#include <math.h>

// 構造体の定義
struct Person {
    char name[50];
    int age;
    float height;
};

// typedef を使った型定義
typedef struct {
    int x;
    int y;
} Point;

// 構造体を引数として受け取る関数
void printPerson(struct Person p) {
    printf("名前: %s, 年齢: %d歳, 身長: %.1fcm\n", 
           p.name, p.age, p.height);
}

// 構造体のポインタを引数として受け取る関数
void updateAge(struct Person *p, int newAge) {
    p->age = newAge;
}

// 距離を計算する関数
float distance(Point p1, Point p2) {
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;
    return sqrt(dx * dx + dy * dy);
}

int main() {
    // 構造体の初期化
    struct Person person1 = {"太郎", 25, 175.5};
    struct Person person2;
    
    // 個別に値を設定
    strcpy(person2.name, "花子");
    person2.age = 23;
    person2.height = 162.0;
    
    printPerson(person1);
    printPerson(person2);
    
    // 年齢を更新
    updateAge(&person1, 26);
    printf("更新後: ");
    printPerson(person1);
    
    // Point構造体の使用
    Point p1 = {0, 0};
    Point p2 = {3, 4};
    printf("点(%d, %d)と点(%d, %d)の距離: %.2f\n", 
           p1.x, p1.y, p2.x, p2.y, distance(p1, p2));
    
    return 0;
}

ファイル入出力

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file;
    char filename[] = "sample.txt";
    char buffer[100];
    
    // ファイルに書き込み
    file = fopen(filename, "w");
    if (file == NULL) {
        printf("ファイルを開けませんでした: %s\n", filename);
        return 1;
    }
    
    fprintf(file, "これはC言語のサンプルです。\n");
    fprintf(file, "ファイル入出力の例です。\n");
    fprintf(file, "数値: %d\n", 42);
    fclose(file);
    
    printf("ファイルに書き込みました: %s\n", filename);
    
    // ファイルから読み込み
    file = fopen(filename, "r");
    if (file == NULL) {
        printf("ファイルを開けませんでした: %s\n", filename);
        return 1;
    }
    
    printf("\nファイルの内容:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    fclose(file);
    
    return 0;
}

プリプロセッサとマクロ

#include <stdio.h>

// マクロ定義
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

// 条件付きコンパイル
#ifdef DEBUG
    #define DBG_PRINT(x) printf("DEBUG: %s\n", x)
#else
    #define DBG_PRINT(x)
#endif

int main() {
    // マクロの使用
    float radius = 5.0;
    float area = PI * SQUARE(radius);
    
    printf("半径 %.1f の円の面積: %.2f\n", radius, area);
    
    int a = 10, b = 20;
    printf("MAX(%d, %d) = %d\n", a, b, MAX(a, b));
    
    // デバッグ出力(DEBUGが定義されている場合のみ)
    DBG_PRINT("プログラムが正常に動作しています");
    
    // コンパイラ情報
    printf("コンパイル日時: %s %s\n", __DATE__, __TIME__);
    printf("ファイル名: %s\n", __FILE__);
    printf("行番号: %d\n", __LINE__);
    
    return 0;
}

メリット・デメリット

メリット

  • 高性能: 効率的なコード生成とメモリ使用
  • ハードウェア制御: 低レベルなハードウェアアクセスが可能
  • 移植性: 多くのプラットフォームで利用可能
  • コンパクト: 必要最小限の機能でシンプル
  • 影響力: 多くの言語の基礎となった
  • 豊富な資料: 長年の蓄積による学習リソースの充実

デメリット

  • メモリ管理: 手動でのメモリ管理が必要
  • 安全性: バッファオーバーフローなどのセキュリティリスク
  • 学習コスト: ポインタや低レベル概念の理解が必要
  • 開発効率: 高水準言語と比較して開発時間が長い
  • 文字列処理: 文字列操作が煩雑

主要リンク

ランキング情報

  • 総合ランキング: 8位
  • TIOBE Index: 3位
  • PYPL PopularitY: 4位
  • GitHub使用率: 10位
  • RedMonk言語ランキング: 10位
  • IEEE Spectrum: 9位
  • JetBrains開発者調査: 10位

C言語は、システムプログラミングの基礎として、多くのプログラミング言語とシステムの土台となる重要な言語です。