C 备忘

动机

  • hack
  • 硬件
  • microblocks vm
  • squeak vm

标准

ANSI C

C89

现在多数C代码是在ANSI C基础上写的

C11

Linux 内核正迁移到 C11

变长数组 vla

C18

C语言的现行标准

特性

  • 有变量作用域以及递归功能的过程式语言
  • 传递参数均是以值传递(pass by value),外也可以传递指针(a pointer passed by value)
  • 不同的变量类型可以用结构体(struct)组合在一起
  • 部分的变量类型可以转换,例如整数型和字符型变量。
  • 透过指针(pointer),C语言可以容易的对存储器进行低端控制

支持C18的编译器有:

  • GCC 8.1.0
  • LLVM Clang 7.0.0
  • IAR EWARM v8.40.1

备忘

Hello World

1
2
3
4
5
6
7
#include <stdio.h> // 预处理器会将#include <stdio.h>替换为stdio.h文件的内容

int main(void) // 程序从 main 开始执行
{   
    printf("Hello, world!\n"); // printf是声明于stdio.h的函数
    return 0; // 返回一个值给调用程序的壳层,表明程序是否成功运行
}

指针

如果一个变量声明时在前面使用 * 号,表明这是个指针型变量。换句话说,该变量存储一个地址

而 * 则是取内容操作符,意思是取这个内存地址里存储的内容。

可将 int *a;看作是 “*a 解得的内容类型为 int”

指针是一把双刃剑,许多操作可以通过指针自然的表达,但是不正确的或者过分的使用指针又会给程序带来大量潜在的错误。

&,叫做取地址运算符,它将返回一个变量、数组或函数的存储地址。

函数

C语言的基本结构单位是函数

功能和封装的集合,称为“标准库”,标准库的声明头部通过预处理器命令#include进行引用。

VLA

无法将 C 中可变长度数组声明为全局变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 您可以(并且应该)做的是动态分配它:
// 在 microblocks MQTT primitives 里使用
char* my_dynamic_array = NULL;

void f(unsigned int size)
{
    if(!my_dynamic_array) {
        my_dynamic_array = malloc(size);
    }
    /* do something with the array */
}

int main(void)
{
    f(1024); /* set size dynamically */
    /* do something with the array */
    free(my_dynamic_array); /* free the allocated memory */
    return 0;
}

hard way

hello world

1
2
3
4
5
6
7
#include <stdio.h>
int main(int argc, char *argv[])
{
    puts("Hello world.");

    return 0;
}
1
2
CFLAGS="-Wall" make ex1
./ex1

todo: https://wizardforcel.gitbooks.io/lcthw/content/ex2.html

参考