由于自己C语言基础不是很扎实,最近在学习 ==《C与指针》==所以最近可能会定期记录一下自己的学习心得和笔记。
编译过程的几个阶段
1、预处理器阶段
- 主要工作是用实际值代替==#define指令定义的符号,读入#include==包含的文件内容,处理条件编译,以及去掉注释等。
- 在Linux/Unix下源文件被处理为:main.i sort.i
2、编译阶段
- 主要工作是检查程序中存在的语法错误,或是给出警告,最后生成汇编代码
- 在Linux/Unix下文件被处理为: main.s sort.s
3、汇编阶段
- 主要工作是将汇编代码转换为二进制代码
- 在Linux/Unix下源文件被处理为:main.o sort.o
4、链接阶段
- 主要工作是将所有目标文件链接到一起,生成一个单一完整的可执行程序
- 在Linux/Unix下文件被处理为:a.out 或可通过-o name 将可执行程序命名为name文件
- 在windows下文件被处理为:xxxx.exe
注:在到达链接阶段之前,所有文件均各自独立处理,不会发生交互。
词法规则
三字母词:指的是几个字符的序列,合起来表示另一个字符
三字母词 | 含义 |
---|---|
???( | [ |
???) | ] |
???! | I |
???< | { |
???> | } |
???’ | ^ |
???= | # |
???/ | \ |
???- | ~ |
转义序列,字符转义
标识符
- 标识符是变量、函数、类型的名字,有大小写字母、数字和下划线组成,但是不能以数字开头,C是一个对大小写敏感的语言,abc,aBc,ABC,Abc是四种不同的标识符
- 在C语言中,对标识符没有长度的限制,但是标准规定允许编译器忽略第31位字符以后的字符。
数据
C语言中的4种基本数据类型
- 整形 浮点型 指针 聚合类型(数组/结构体)
- 整形家族:int(整形) char(字符型) short(短整型) long int(长整形)
- 均分有符号(signed)和无符号(unsigned)
- 注:C语言没有规定长整型必须比整形长,但是C语言规定,长整型至少和整形一样长,整形至少和短整型一样长。
- 头文件limits.h中说明各种不同整形类型的特点
- 浮点类型:float(单精度浮点型) double(双精度浮点型) long double(扩展精度)
- 标准规定浮点型表示的最小范围:10^-37 – 10^37
- 浮点型的字面值,标准规定必须有一个小数点或是一个指数e,或者二者都有:3.14159 1E10 25. .5 6.023e23
指针
字符串常量
- 注:在K&R C中规定,具有相同值得不同字符串常量在内存中是分开存在的,因此在K&R C中是支持修改字符串常量的值的。
- 注:在ASNI C中声明若是对一个字符串常量进行修改,结果是未定义的,因为它允许编译器将具有相同值得字符串常量存储在一块内存中,即使该字符串常量在程序中多次出现,因此最好不要修改一个字符串常量,即便编译器允许,因为对一个字符串常量进行修改可能会影响到程序中的其他字符串常量,若需对字符串常量进行修改,最好将其存储在数组中。
- 这里我们来理解一句话,不能把字符串常量赋值给一个字符数组
首先我们来看一段代码
#include <stdio.h>
int main()
{
char a[] = "abcdef";
a[] = "ghjk";
return 0;
}
这样的操作是不被允许的,编译器会报错,说a[]是不能被修改的左值,因为a[]表示的是一个地址,是不允许被修改的。
int main()
{
char a[] = "abcdef";
a[0] = 'b';
a[1] = 'r';
return 0;
}
这样的操作是允许的,a[0]、a[1] 是表示的数组a中的值,是可以被修改的。
- C语言标准规定,对于字符串常量,可以单个引用,但是不能整体赋值
- 若想要整体拷贝字符串,可以借用字符串函数来实现,如:strcpy,strcat等,可参考博客https://blog.csdn.net/chenxiyuehh/article/details/88227492
指针的声明
- 指针的声明最好写成
int *a,*b,*c
不要写成int* p
虽然后者更好理解,但是容易出错 char *message = "hello world!"
这里是将字符串常量的第一个字符的地址赋值给message,而不是给*message- 也可以写成
char *message; message = "hello world!"
关键字typedef
- 注:尽量使用typedef来创建新的类型名,而不是用#define
这里我们来看一段代码
#include <stdio.h>
#define d_ptr_to_char char*
typedef char* ptr_to_char;
int main()
{
ptr_to_char a, b;
d_ptr_to_char c, d;
b = "abcj";
d = "hgjfgj";
return 0;
}
注:这里我们可以看到,其实对于d_ptr_to_char c, d;等价于char* c,d;此时将c定义为一个字符指针,但是d却是一个字符,而ptr_to_char a, b;才是真正将a,b定义成为了两个字符指针。