重新審視C語言:語言基礎

Author Avatar
高宇哲 3月 23, 2017

C的特性

  • 原始碼可攜性
  • 面對硬體的能力
  • 效率

C的歷史

C可追溯到Richard Martin開發的BCPL語言,1978年出版了第一份C語言的官方文件,簡稱K&R。

C程式的結構

觀察以下程式碼

// circle.c: Calculate and print the areas of circles
#include <stdio.h> // Preprocessor directive
double circularArea( double r ); // Function declaration (prototype form)

int main() // Definition of main() begins
{
    double radius = 1.0, area = 0.0;

    printf( " Areas of Circles\n\n" );
    printf( " Radius Area\n"
    "-------------------------\n" );

    area = circularArea( radius );
    printf( "%10.1f %10.2f\n", radius, area );
    radius = 5.0;
    area = circularArea( radius );
    printf( "%10.1f %10.2f\n", radius, area );
    return 0;
}

// The function circularArea( ) calculates the area of a circle
// Parameter: The radius of the circle
// Return value: The area of the circle
double circularArea( double r ) // Definition of circularArea( ) begins
{
    const double pi = 3.1415926536; // Pi is a constant
    return pi * r * r;
}

circularArea()的原型(Prototype)宣告提供了必要的資訊,呼叫此函式的陳述式能得以編譯。但circularArea()放在main()之前,這讓該函式原型宣告變得多餘,這是因為函式的定義本身就是宣告。於是我們可以把C程式先定義到別的C程式中

C語言的原始檔

通常C語言的原始檔具有下列三點特性

  • 前置處理器指示詞
  • 全域宣告
  • 函式定義

考慮以下程式碼

// circle.c: Calculate and print the areas of circles
#include <stdio.h> // Preprocessor directive
double circularArea( double r ); // Function declaration (prototype form)

int main() // Definition of main() begins
{
    double radius = 1.0, area = 0.0;

    printf( " Areas of Circles\n\n" );
    printf( " Radius Area\n"
    "-------------------------\n" );

    area = circularArea( radius );
    printf( "%10.1f %10.2f\n", radius, area );
    radius = 5.0;
    area = circularArea( radius );
    printf( "%10.1f %10.2f\n", radius, area );
    return 0;
}
// circulararea.c: Calculates the areas of circles.
// Called by main() in circle.c

double circularArea( double r ) // Definition of circularArea( ) begins
{
    const double pi = 3.1415926536; // Pi is a constant
    return pi * r * r;
}

每個C原始檔構成了轉譯單位(Translation Unit),編譯器會依序處理轉譯單位的內容,將原始碼解析成最小的語意單位,稱作符記(Token)

但是在有許多C程式的情況下我們要如何進行編譯呢,我們可以建置一個Makefile來編譯以上程式

# A basic makefile for "circle".

CC = gcc
CFLAGS = -Wall -g -std=c99
LDFLAGS = -lm

circle : circle.o circulararea.o
    $(CC) $(LDFLAGS) -o $@ $^
circle.o : circle.c
    $(CC) $(CFLAGS) -o $@ -c $<
circulararea.o: circulararea.c
    $(CC) $(CFLAGS) -o $@ -c $<

只要將以上程式放在原始檔同一層下make指令就能進行編譯,可以參考猴子都會寫的Makefile,完整程式碼已放於github

參考資料:C in a nutshell