中国大学MOOC-翁恺C语言-学习笔记(二)

第四部分(函数、数组、字符串)

  1. 函数
    (1)函数是一块代码。接受零个或多个参数,做一件事情,返回零个或一个值
    (2)每个函数都有自己的变量空间,这个函数的参数也位于这个独立空间中,和其他函数没有关系。
    在这里插入图片描述

  2. 调用函数时给的值与参数的类型不匹配是C语言传统上最大的漏洞。后续语言如:C++、Java等在这方面很严格。

  3. 数组的大小:sizeof(a) 可给出数组 a[ ] 所占据的内存字节数。
    数组的元素个数:sizeof(a) / sizeof(a[0]) 可求出数组元素个数。

使用 sizeof(a) / sizeof(a[0]) 的好处是:一旦修改数组中初始的数据,不需要修改遍历的代码。

  1. 二维数组的列数必须给出,行数可以由编译器来数。

  2. 防止数组下标越界的一种方法:

char string [8];
scanf("%7s",string);
  1. 如果要把一个数组的所有元素交给另一个数组,必须采用遍历,不能直接赋值。

  2. 数组作为函数参数时
    (1)不能在 [ ] 中给出数组的大小;
    (2)不能再利用 sizeof 来计算数组的元素个数,需引入另一个参数来传入数组的大小。

  3. 字符串
    在这里插入图片描述

  4. 字符串常量

若:char *s = "Hello World !"; 则说明:s是一个指针,初始化为指向一个字符串常量。此时,试图对s所指的字符串做写入会导致严重的后果。

第五部分(指针、结构)

  1. &:获取变量的地址。& 不能对没有地址的东西取地址,如常量就没有地址。故地址符的右边必须有一个明确的变量,即操作数必须是变量。

  2. 指针就是保存地址的变量。指针变量的值就是内存的地址,是具有实际值的变量的地址

  3. 无论指针指向什么类型,所有的指针的大小都是一样的,因为都是地址。

  4. 指向不同类型的指针是不能直接互相赋值的,这是为了避免用错指针。但如果非要互相赋值,可以进行强制类型转换。

  5. 指针的使用场景
    (1)需要将较大的数据传入函数时,可用作函数参数;
    (2)将其传入数组,对数组进行操作;
    (3)需要用函数来修改不止一个变量时;
    (4)当函数返回不止一个结果时;

  6. *p++:取出 p 所指的那个数据来,完事后顺便把 p 移到下一个位置去。常用于数组类的连续空间操作。

  7. 数组指针、指针数组
    (1)指针数组:首先它是一个数组,数组的元素都是指针。数组占多少个字节由数组本身的大小决定。它是“储存指针的数组”的简称。
    (2)数组指针:首先它是一个指针,它指向一个数组。在 32 位系统下任何类型的指针永远只占 4 个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小。它是“指向数组的指针”的简称。

  8. malloc 动态内存分配:
    (1)头文件:#include <stdlib.h>
    (2)void* malloc(size_t size)
    (3)利用 malloc 函数申请的空间的大小是以字节为单位的
    (4)返回的结果是void*,需要类型转换为自己需要的类型;
    (5)如果申请失败,则返回0,或者叫做NULL;
    (6)使用完后,注意将申请得来的空间 free “系统”。

  9. const 与指针

const 在星号前面,通过指针所指的东西不可修改
const 在星号后面,指针不可修改

const int *p = &i; 
*p = 26; //错
i = 26; //OK
p = &j; //OK
int i;
const int *p1 = &i; //通过指针所指的东西不可修改
int const *p2 = &i; //通过指针所指的东西不可修改
int *const p3 = &i; //指针不可修改
  1. char* 是字符串吗?

char* 的本意是:指向字符的指针。
字符串可以表达为 char* 的形式。但 char* 不一定是字符串,可能是指向字符的数组。

  1. typedef 可自定义数据类型。

  2. 要访问整个结构,可直接用结构变量的名字。但结构和数组不同,结构变量的名字并不是结构变量的地址,故必须使用 & 运算符。

  3. 指向结构的指针:用 -> 表示指针所指的结构变量中的成员。

struct date {
   int month;
   int day;
   int year;
} myday;

struct date *p = &myday;

(*p).month = 12; //第一种
p->month = 12; //第二种

第六部分

  1. #:指出编译预处理指令

除常见的编译预处理指令外,还有其它编译预处理指令如:条件编译、error 等。

  1. #define:用来定义一个宏。宏有:有值的宏、没值的宏、预定义的宏、像函数的宏。
const double PI = 3.14159;
#define PI 3.14159
  1. 枚举是一种用户定义的数据类型,它用关键字 enum 以如下语法来声明:
    (1)enum 枚举类型名字 {名字0,……名字n}
    (2)声明枚举量的时候可以指定值,如:
    (3)虽然枚举类型可以当作类型使用,但实际上很少用(不好用)。
    (4)如果有意义上排比的名字,用枚举比const int 方便;
    (5)枚举比宏好用,因为枚举有int类型。
enum COLOR { RED=1, YELLOW, GREEN=5, NumCOLORS };
  1. 定义带参数的宏时需遵循的原则:
    (1)参数出现的每个地方都要有括号;
    (2)整个值要有括号;
    (3)一切都要有括号。

  2. 带参数的宏在大型程序的代码中使用非常普遍,它虽牺牲了空间,但赢取了效率。

  3. 没有值的宏是用于条件编译的,后面有其他的编译预处理指令来检查这个宏是否已经被定义过。

#define _DEBUG
  1. #include的误区:
    在这里插入图片描述

  2. #include 有两种形式来指出要插入的文件:< > 和 “ ”
    (1)“ ” 要求编译器首先在目前目录中(源文件所在的目录)寻找这个文件。如果没有,再到编译器指定的目录去寻找这个文件。
    (2)< > 要求编译器只在指定的目录中寻找。

  3. 标准头文件结构:
    在这里插入图片描述

  4. 头文件里只能放声明。

  5. 声明不产生代码。

第七部分

  1. 全局变量:定义在函数外面的变量,具有全局的生存期和作用域,在任何函数内部都可使用。
    (1)没有做初始化的全局变量会得到0值,指针会得到NULL值;
    (2)如果函数内部存在与全局变量同名的变量,则全局变量会被隐藏;
    (3)全局变量的初始化发生在main函数之前。

  2. 本地变量:定义在函数内部的变量和函数参数都属于本地变量。本地变量的生存期和作用域都是大括号

  3. 静态本地变量:在定义本地变量时加上 static 修饰符就可成为静态本地变量。
    (1)在函数离开时,静态本地变量会继续存在并保持其值;
    (2)静态本地变量实际是特殊的全局变量。静态本地变量和全局变量位于相同的内存空间。
    (3)具有全局生存期,函数内的局部作用域

注:应尽量避免使用全局变量,且不要用全局变量在函数之间传递参数和结果。

  1. 按位运算:按位与 &、按位或 |、按位取反 ~、按位异或 ^

  2. 按位与 & 的两种应用
    (1)让某一位或某些位为0:x & 0xFE
    (2)取一个数中的一段:x & 0xFF

  3. 按位或 | 的两种应用
    (1)让某一位或某些位为1:x | 0x01
    (2)把两个数拼起来:0x00FF | 0xFF00

  4. 按位异或 ^ :对一个变量用同一个值异或两次,等于什么也没做。如:x^ y^ y = x

  5. 左移:<<
    (1)x<<=n 等价于 x *= n
    (2)左移后右边填入0。

  6. 右移:>>
    (1)x>>=n 等价于 x /= n
    (2)对于unsigned类型,右移后左边填入0。
    (3)对于signed类型,右移后左边填入原来的最高位(保持符号不变)。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值