Loading

前言:本篇文章主要用于记录博主本人从事C软件开发过程中遇到的各种疑难杂症和奇技淫巧,以知识点的形式将其总结,以做后观。(亦是记录博主如何从C语言小白一步一步走向软件开发......)

1 const

const用以声明变量永不变化的常数。一般来说这些变量都应该被放在ROM区(也就是Flash程序空间)以节约宝贵的RAM内存。但一个简单的const声明并不能保证变量最后会被分配到ROM区,安全的做法必须配合#pragma声明的CONST_SEG或INTO_ROM数据段一起实现。
任何类型的变量,都可以冠以const声明。

2 运算符

  • %:取余数
  • >>:移位运算符。a >>= b相当于 a = a >> b,将二进制a右移b位(低位丢弃)
  • &&:逻辑与运算符
  • &:位与运算符。a &= b 相当于 a = a & b,按位与运算之后赋值给a
  • ||:逻辑或运算符
  • |:位或运算符
  • ^:异或运算符,位运算的一种。a ^= b,a、b相同a为0,a、b不同a为1
  • ! :逻辑非运算符。!0为真,其余为假
  • ~:按位取反运算符

3 数据格式声明

格式字符:

  • %d:有符号十进制整数
  • %c:一个字符
  • %s:一个字符串
  • %f:输出实数【以小数形式,默认实数的整数部分全部输出,小数部分输出6位】
  • %e:以指数形式输出实数
  • %ld、%lld:长整型数据、双长整型数据
  • %x:十六进制数

% 是格式声明符,若想输出 %,则应连用两个 % 表示,例如:printf("%%\n");

  • %m.nf:m代表输出数据的宽度,该宽度包括整数。n代表输出数据的小数位数(末尾以四舍五入原则,若格式为%-m.nf,表示数据向左对齐)
  • %m.ns:m代表输出字符的宽度,n代表只打印前n个字符(%-m.ns标记使得文本左对齐输出)

4 逃逸字符

  • \b:回退一格
  • \t:到下一个表格位
  • \n:换行
  • \r:回车
  • \’:单引号
  • \”:双引号
  • \\:反斜杠本身

\ 在C语言中被称之为转义字符。

5 scanf函数

scanf类似于一个获取单词的函数,若用其读取字符串,从第一个非空白字符作为字符串的开始,以下一个空白字符作为字符串的结束。若指定了字段宽度,则在读取字段宽度的字符或读到空白字符后结束。其具有返回值,可以分成以下3类情况:

  1. 正整数:表示成功读取的项数
  2. 0:表示用户输入的值不匹配
  3. EOF:表示检测到“文件结尾”

scanf中的 * :用于抑制赋值

6 取整相关

  • i=(int)2.5; // int:直接舍去小数部分,i=2
  • floor(x); // 返回的是小于或等于x的最大整数
  • ceil(x); // 返回的是大于x的最小整数

7 单反斜杠(\)的作用

  1. 可以作为转义字符使用,例如 \n 表示换行符
  2. 可以作为续行符使用,用于一行的结尾,表示本行与下一行连接起来

8 switch 与 if

  • 若根据浮点类型的变量或表达式来选择,则无法使用 switch
  • 若根据变量在某范围类决定程序流的去向,则推荐使用 if
  • 使用 switch 程序通常运行快一些,生成的代码少一些

9 for

for 循环后面直接加分号,则表示只进行 for 循环而跳过后面的语句。且当其后面没有语句时,必须要加一个分号。

10 链表和数组

选择何种数据类型取决于具体的问题。

  • 如果因频繁地插入和删除项导致经常调整大小,而且不需要经常查找,选择链表会更好。
  • 如果只是偶尔插入或删除项,但是经常进行查找,使用数组会更好。
  • 如果既需要频繁插入和删除项,又要频繁查找,则选择二叉查找树。

11 const与数组

a[] = {1,2,3,4,5};  // 表示a只能指向该数组, 不能指向其他数组
const int a[] = {1,2,3,4,5};  // 不止a为const的指针,数组内部的每个单元都是const int类型,若有以上类型定义,则必须通过初始化进行赋值

12 const与指针

int* const q = &i;  // 指针本身被定义为const
// 表示一旦q得到了某个变量的地址,其就不可以再指向其他变量, q只能指向一个固定的地址
*q = 26;  // ok
q++;      // ERROR

const int* p = &i;  // 指针所指的变量被定义为const
// 表示不能通过这个指针去修改指向的变量的值(并不表示指向的变量变成const)
*p = 26; //error
i = 26;  // ok
p = &j;  // ok

13 数组指针

数组指针定义:int (*p)[n];

()优先级高,先与p结合成为一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

// 将二维数组赋给数组指针: 
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。

p=a;  // 将该二维数组的首地址赋给p, 也就是a[0]或&a[0][0]
p++;  // 该语句执行过后, 也就是执行p=p+1后, p跨过行a[0][]指向了行a[1][]
// 所以数组指针也称指向一维数组的指针, 亦称行指针。

14 指针数组

指针数组定义:int* p[n];

[]优先级高,先与p结合成为一个数组,再由 int* 说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,p会指向下一个数组元素。

// 将二维数组赋给指针数组: 
int a[3][4];
int* p[3];

for (i=0; i<3; i++)
{
    p[i]=a[i];
}  
// 这里int* p[3]表示一个一维数组内存放着三个指针变量, 分别是p[0]、p[1]、p[2], 所以要分别赋值

// p=a; 这样赋值是错误的
// 因为p是个不可知的表示, 只存在p[0]、p[1]、p[2]…p[n-1], 而且它们分别是指针变量可以用来存放变量地址。
// *p=a; 这样赋值是可以的, *p表示指针数组第一个元素的值, 即相当于 p[0] = a[0][]

通过以上,数组指针和指针数组两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

当数组指针和指针数组都指向二维数组,要表示数组中i行j列的一个元素时,以下引用方式等价:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

符号优先级:()>[]>*

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

👤本站访客数: 👁️本站访问量: