C程序设计语言(一)导言,类型、运算符与表达式

观感

  C语言之父写的C语言指南,阅读的时候怎么能不怀着一点点崇敬的心情。
  这本书的第一观感是真的很薄,一共250+页,从167页开始就是附录了。整个目录只有3页纸,这么薄的书在我的书架上只有《C陷阱与缺陷》能够一战。
  进入到正文开始阅读后发现,信息量真的很大,要在这一百多页中介绍C语言的基本使用,信息密度可想而知。读起来并不轻松,不是太推荐C语言纯新人阅读,真怕造成“C语言从入门到放弃”。

目的

  这里我摘录一些读书的心得和要点,进一步压缩篇幅,方便自己在时间紧迫的情况下快速梳理所有要点。

准备

  为了验证书中的代码和做书中的练习,需要准备一个能够编译和运行C语言程序的环境。为了简便起见,我使用了ubuntu系统,命令行方式编译运行比较方便快捷。
  为了少打一些字,提高效率,使用以下Makefile来编译目录下所有的.c文件到对应的可执行文件:

[Makefile]
src := $(wildcard *.c)
obj := $(patsubst %.c, %.o, $(src))
out := $(patsubst %.o, %, $(obj))
%.o: %.c
    gcc -c -o $@ $<
%: %.o
    gcc -o $@ $^
all: $(out)
clean:
    rm -f $(obj) $(out)

  这样,每次修改或者新编写了一个C语言程序源文件后,直接在命令行执行 make 就可以了。
  

基本概念

类型

  • C程序的3个组成要素:变量、函数、语句
  • C程序处理的数据对象:变量、常量
    • 变量有类型 - int float char short long double
    • 常量也有类型
      • 1234 int型
      • 1234L long int型
      • 1.0 double型
      • 1.0f float型
      • 1.0L long double型
      • 0XFUL unsigned long类型,值为15
      • ‘c’, ‘\n’, ‘\123’,’\0x20’ 都是字符型常量
      • 字符串或者字符串常量,“hello world\n”
  • printf函数不会自动添加换行符,多条printf并不会自动产生行的输出
  • 转义字符序列,escape sequence,\n \t \b \” \\
#include <stdio.h>
int main()
{
    printf("hello ");
    printf("world");
    printf("\n");
    return 0;
}
  • 变量必须先声明后使用,声明位置在函数起始处,执行任何语句之前
  • 建议每行只书写一条语句,运算符两边加上空格
  • %3d 右对齐占用几个字符空间,%3.1f 小数点保留几位
  • 5 / 9,5.0 / 9.0 ,整数舍位,浮点常数也要写成浮点的样式
#include <stdio.h>
int main()
{
    float fahr, celsius;
    int lower = 0;
    int upper = 300;
    int step = 20;

    printf("exercise 1_3\n");
    printf("\tFahr to Celsius\n");
    fahr = lower;
    while(fahr <= upper)
    {
        celsius = (5.0 / 9.0) * (fahr - 32);
        printf("%3.0f\t%6.1f\n", fahr, celsius);
        fahr = fahr + step;
    }
    return 0;
}
  • %o %x %s %%
  • 可以出现变量值的位置,都可以用产生该变量的表达式
  • #define 定义符号常量,通常大写,末尾没有分号,预编译替换的时候如果不在引号内,不是更长名字的一部分,都会按照#define替换
#define LEAP    1 /* 闰年*/
int days[31 + 28 + LEAP + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31];  /* 这些数字常量和符号常量在编译的时候,就进行了求值,所以编译之后就是一年的天数了*/
  • 文本流,包括多行字符,每行包括0个或者多个字符,每行以换行符结尾,文本流以EOF(end of file)结尾,EOF长度超过字符类型,一般定义成FFFFFFFF (-1)
  • c = getchar(),从文本流读入下一个字符,putchar(c)向屏幕输出一个字符
#include <stdio.h>
int main()
{
    int c;
    while((c = getchar()) != EOF)
        putchar(c);
    return 0;
}

运算符

  • 自增自减,前缀后缀,n++, ++n
  • 使用更大的整数表示范围,用double 类型,当做整数运算
  • 关系运算符 == ,!=, >, >=, <, <=
  • 位运算符 &, |, ~, <<, >>
  • 字符常量,单引号内部的一个字符,数值是一个比较小的整数,’A’, ‘\t’
#include <stdio.h>
int main()
{
    double nl;
    int c;
    nl = 0;
    while((c = getchar()) != EOF)
    {
        if (c == '\n')
            nl++;
    }
    printf("line number: %.0f\n", nl);
    return 0;
}
  • 逻辑运算符 && , ||, !,遵循短路求值
  • 函数的定义,存放的位置不重要,只要不跨文件即可
  • 函数的参数传递,是值传递,不是引用传递;形参名称只在函数内部有意义
  • 编译时遇到函数名,需要已经声明过,但可以不必知道定义在哪里
  • 字符串以’\0’标记结束
/* strlen函数:返回字符串s的长度*/
int strlen(char s[])
{
    int ;
    i = 0;
    while(s[i] != '\0')
        ++i;
    return i;
}

变量

  • 变量类型
    • 自动变量 - 函数内部定义的变量,作用域函数内部,生存期函数执行
    • 外部变量 - 函数外部定义的变量,只定义一次,编译器为其分配存储单元。使用的时候先声明
      • 声明在函数内部,从声明的位置起到本函数结束有效
      • 声明在函数外部,从声明的位置起到本文件结束有效
      • 外部变量定义在某个c文件中(此文件中使用它不需要声明为extern,直接用就可以),通常声明在h文件中(使用它的各c文件需要Include这个头文件)
    • 静态变量
      • static 全局变量 - 本文件可见,程序的其他文件不可见,名字不会冲突
      • static 局部变量 - 本函数可见,却别于自动变量,函数结束也不会释放
  • 复杂类型变量
    • 枚举
    • 结构
    • 联合
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
enum months a;
enum months b;
a = JAN;
b = MAY;
  • 变量声明
    • 显式,隐式,形参就是隐式声明
    • 声明同时可以进行初始化
    • 建议一个变量单独用一行声明
    • 全局或者静态变量的声明可以同时进行初始化,初始化的动作只进行一次
    • 声明时可以使用const限定符,表示不可以修改,数组的话,表示数组的所有元素都不能修改

一些有意思的小程序

/* atoi函数:将字符串s转换为相应的整数*/
int atoi(char s[])
{
    int i;
    int n = 0;
    for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
    {
        n = 10 * n +(s[i] - '0');
    }
    return n;
}

/* strcat函数:将字符串t接到字符串s的尾部,s必须有足够大的空间*/
void strcat(char s[], char t[])
{
    int i, j;
    i = j = 0;
    while (s[i] != '\0')
        i++;
    while((s[i++] = t[j++]) != '\0')
        ;
}

/* getbits函数:返回x中从第p位开始的n个位*/
unsigned getbits(unsigned x, int p, int n)
{
    return (x >> (p + 1 - n)) & ~(~0 << n);
}
/* 删除数字最右边的一位值为1的二进制位*/
/* 可以用于快速判断是否是只有一个位等于1的二进制数 */
x &= (x - 1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值