C言語（シーげんご、）は、1972年にAT&Tベル研究所のデニス・リッチーが主体となって開発した汎用プログラミング言語である。英語圏では「C language」または単に「C」と呼ばれることが多い。日本でも文書や文脈によっては同様に「C」と呼ぶことがある。制御構文などに高水準言語の特徴を持ちながら、ハードウェア寄りの記述も可能な低水準言語の特徴も併せ持つ。基幹系システムや、動作環境の資源制約が厳しい、あるいは実行速度性能が要求されるソフトウェアの開発に用いられることが多い。後発のC++やJava、C#など、「C系」と呼ばれる派生言語の始祖でもある。

ANSI、ISO、またJISにより言語仕様が標準規格化されている。

 特徴 

Cには他のプログラミング言語と比較して、特筆すべきいくつかの特徴がある。

 利点 
 構造化プログラミングのパラダイムに対応した高水準の手続き型言語である。ハードウェアの直接的な制御ができる機能を備えつつ、機械語やアセンブリ言語（アセンブラ）のような低水準言語と比較して、ソースコードの再利用性やメンテナンス性に優れており、目的に応じたプログラムの変更や拡張が容易である。
 汎用性およびプログラムの自由度が高く、リソースや性能要求の厳しい用途にも耐えうるため、アプリケーションソフトウェアの開発だけでなく、オペレーティングシステム（OS）やデバイスドライバー、ファームウェアの記述、マイコン制御・機械制御など、上位層・下位層を問わず、あらゆる分野で利用されている。
 対応する機器の範囲が広い。パーソナルコンピュータやワークステーションはもちろん、自動車や家電の組み込み用マイコンからスーパーコンピュータまで、C言語を使用できるハードウェアは多様である。そのため、C言語のコード資産が蓄積されている環境・分野は多岐に渡る。
 商用・非商用を問わず、採用ソフトウェア分野が広い。プログラム作成やデバッグのための補助的なソフトウェア（プログラミングツール）が豊富である。
 ソースコードを機械語に変換するソフトウェア（コンパイラ）などの開発環境がCPUやOSに付属していたり無償だったりするものもあるため、ライセンス料の支払いをしなくても使用が始められる。

 欠点 
 開発時期が古いことから、言語構文（文法）に機械語の影響が強く、仕様自体は単純ではあるが明快ではなく難解である。この欠点を改良するためのちに開発された後発言語に比較し、プログラマが記述しなければならないことが多く、低水準言語のように面倒で習得しにくい側面を持つ。
 Cは、移植の容易性、自由度、実行速度、コンパイル速度などを追求した。代わりにコンパイル後のコードの安全性を犠牲にしている。また、詳細を規格で規定せず処理系に委ねている部分が多く、Cで書かれたソフトウェアでは処理系依存のコードが氾濫する原因となった。セキュリティ上の脆弱性や潜在的バグによる想定外の動作、コンパイラによる最適化の難しさといった問題を抱えており、最適化するとコンパイル速度が遅くなるなどの問題が生じることがある。

上記のように、利点でもあり、同時に欠点にもなる特徴を備えている。

もともとUNIXおよびCコンパイラの移植性を高めるために開発されてきた経緯から、オペレーティングシステム（OS）のカーネルおよびコンパイラ向けの低水準な記述ができるなど、ハードウェアをある程度抽象化しつつも、必要に応じて低水準言語と同じことを実現できるようなコンピュータ寄りの言語仕様になっている。そのため、低水準な記述ができる高水準言語と言われたり、高水準言語の顔をした低水準言語（高級アセンブラ、汎用アセンブラ）と言われたりすることがある。

Cはアマチュアからプロ技術者まで、プログラマ人口が多く、プログラマのコミュニティが充実している。使用者の多さから、正負の両面含め、Cはプログラミング文化に大きな影響を及ぼしている。また、多目的性と、対応機器の多彩さのため、「コンピュータを使ってやること」は大抵、Cで対応可能である。ただし、Cで効率的かつ安全に記述できるかどうかはまた別の話である。スクリプト言語やコマンドラインシェルを使えば手軽に実現にできるような処理まで、わざわざCで記述する必要はない。また、GUIアプリケーションフレームワークは、Cからは利用できず、統合開発環境と連携する新しいプログラミングツールやプログラミングパラダイムに対応した後発言語でなければ利用できないものもある。

MISRA CやCERT Cというコーディング標準（コーディング規約）を定義して、危険な機能の使用や記述を禁止するという制限を設けることでCを安全に利用するためのガイドラインが運用されている分野もある。特にプログラミングミスが人命に直結する自動車分野などでCを利用するには、このような制約が重要である。

 機能と自由度 
 文の区切りを終端記号 セミコロン「;」で表し、改行文字にも空白にもトークンの区切りとしての意味しか持たせない「フリーフォーマット」という形式を採用している。中括弧{ }によるブロック構造およびスコープをサポートする。
 ALGOLの思想を受け継いで構造化プログラミングに対応している。手順を入れ子構造で示して見通しの良い記述をすることができる。原理的に無条件分岐（goto）を使用する必要はなく、MISRA Cでは当初goto文を禁止していた。
 モジュール化がファイルを単位として可能。モジュール内だけで有効な名前を使うことができるスコープを持っている。
 プログラムを戻り値つきのサブルーチンに分離できる。C言語ではこれを関数と呼び、関数内のプログラムコードでは、独立したスコープを持つ変数（ローカル変数）が使用できる。これにより、データの流れがブロックごとに完結するのでデバッグが容易になり、また関数の再帰呼び出しも可能となる。また、多人数での共同開発の際にも変数名の衝突が回避しやすくなる。なお、C言語ではUNIXのようなOSを前提としたホスト環境と、割り込み制御のようなOSを前提としないフリースタンディング環境とがある。ホスト環境では、プログラム開始直後に実行するプログラム要素を main という名前の関数として定義する。プログラム中で再帰的にmain関数を呼ぶことも可能（C++では不可能）。フリースタンディング環境では、エントリーポイントと呼ばれるアドレスに置かれたコードをプログラムの開始点とするが、それがmain関数である必要はない。なお再帰呼び出しそのものは、スタックオーバーフローの原因となるため、MISRA Cでは禁止している。
 システム記述言語として開発されたため、高級言語であるがアセンブラ的な低水準の操作ができる。ポインタ演算、ビットごとの論理演算、シフト演算などの機能を持ち、ハードウェアに密着した処理を効率よく記述できる。これはオペレーティングシステムやデバイスドライバーなどを記述する上では便利であるが、注意深く利用しないと発見しにくいバグの原因となる。ライブラリ関数は、C言語規格が規定している関数と、OSが規定している関数との間の整合性、棲み分けなどが流動的である。MISRA Cのようないくつかの制約では、C言語規格が規定している関数の妥当性について指摘し、いくつかの関数を利用しないように規定している。

 ソースコードの記述に使う文字集合はANSI C (C89) およびISO/IEC 9899:1990 (C90) ではASCIIを標準としている。他のISO 646でも書けるように、3文字利用したトライグラフと呼ばれる表記法も存在する。その後、ISO/IEC 9899:1995 AMD (C95) などではマルチバイト文字セット対応の拡張を規定している。さらに、その後トライグラフは複数のコードを利用したシステムでしか利用がないため、より分かり易い2文字によるダイグラフを規定している。
 組み込みの整数型および浮動小数点数型のほか、構造体、共用体、列挙体（列挙型）によるユーザー定義のデータ型や列挙定数をサポートする。構造体および共用体はビットフィールドをサポートする。

 アセンブラとのインタフェース 
 多くの処理系がインラインアセンブラを搭載しているほか、アセンブラで出力したオブジェクトとのリンクが容易になっている。これにより速度が要求される部分だけをアセンブリ言語で記述するということが容易に行えることが多い。アセンブラとのインタフェースは#pragma asmなどを用いて局所化を図る努力はあるが、コンパイラごとに定義があり、CPUが同一であっても移植性が低い場合がある。

 コンパイラ仕様 
 コンパイラの処理が1パスで済む仕様になっている。歴史的な経緯から、変数の宣言において型指定がない場合はint型とみなし、関数の戻り値の型指定がない場合はint型とみなす。ANSI C (C89) ではコンパイル時型検査の強化のために関数プロトタイプの機能が導入されたが、関数の宣言がない場合の戻り値はint型とみなし、引数は未知（任意）とみなす。しかし、このような暗黙の型指定は型安全性を損ない未定義動作を引き起こす危険性があるため、ISO/IEC C:1999 (C99) 以降では暗黙の型指定に関する仕様が標準規格の文面から削除された。いずれも使用（参照）するより前に適切に宣言する必要がある。ClangやGCCといったC99準拠のコンパイラは、このような暗黙の型指定について、C99モードであってもC89互換の動作を残してはいるものの、非標準の動作であるため警告を出すようになっている。なお、関数宣言において()のように引数を省略すると、引数を未知とする仕様はC99でも残されている。後継言語では完全なプロトタイプ宣言を必須とするか、あるいはプロトタイプ宣言自体を不要としているが、記述によっては先読みが必要になりうる。
 マクロ記述やコンパイル条件の指定などができる前処理指令が標準化されている。前処理指令の解釈をするプリプロセッサ (preprocessor) を持っている。プリプロセッサは、その名の通りコンパイル処理の前に自動的に実行される。コンパイラの機能として、プリプロセッサを通しただけの段階のソースコードを出力可能になっているものがある。前処理の結果を検査することで、設計者の意図と前処理の結果のずれがないか確認できる。

 処理系の簡素化 
処理系の簡素化と効率のために、以下のように安全性を犠牲にした仕様が多い。なお、ホスト環境やプログラムの内容によっては、以下に対して脆弱性対策を施したとしても実行速度の低下が無視できる程度であることも多く、言語仕様側の欠点とみなされることも少なくない。
 配列の参照時に添字の値が範囲内にあるかを検査しない
 これを要因とする代表的なバグが、固定長のバッファ領域をはみだしてデータの書き込みが行われてしまう「バッファオーバーフロー」（バッファオーバーラン）である。範囲外のアクセスは、書き込みだけでなく読み取りの場合も未定義動作を引き起こす。標準ライブラリにはバッファオーバーフローや範囲外アクセスを考慮していない関数があり、かつ多用されがちなため、しばしば脆弱性の原因となる。また、Cではプログラムにより明示的に制御（動的メモリ確保）することで可変長配列の実現を可能にしているが、確保した領域の範囲外にアクセスしても自動的な伸長は行なわれない。
 後継言語では、標準ライブラリまたは組み込み型により可変長配列をサポートしていたり、範囲外アクセス時には例外（実行時エラー）を送出するなどして安全性を優先していたりすることが多い。
 文字列を格納するための特別な型が存在しない
 文字列にはchar型の配列を利用する。言語仕様上に特別な扱いはないが、ヌル文字（'\0'）を終端とする文字列表現を使い、その操作をする標準ライブラリ関数がある。これは実質的にメモリ領域へのポインタアクセスそのものであり、確保されている領域の長さよりも長い文字列を書き込めてしまうために、バッファオーバーランの元凶の1つとなっている。
 後継言語では文字列処理を特に強化している場合が多く、標準ライブラリあるいは言語仕様による組み込みの文字列型を提供している。
 自動変数（auto variable）の自動的な初期化をしない
 自動変数（静的でないローカル変数）は変数の中でも最も頻繁に用いられる。初期化されていない変数を参照した場合にはその値は不定であるが、不定な値へのアクセスは未定義動作であるので、コンパイラ最適化の過程で想定しない形に改変することもある。変数宣言・初期化の仕様による制限から、変数宣言の時点では初期化をせずに後で代入等により値を入れてつかうことが普通なので、誤って不定の値の変数を読み出すバグを作り込みやすい。なお自動変数の自動とは変数の領域の確保と解放が自動であるという意味であり、自動的に初期化されるという意味ではない。
 後継言語では、明示的な初期化が記述されていない変数は、不定値ではなくその変数の型の既定値（ゼロあるいはゼロ相当の値）で初期化される仕様になっていることが多い。