C学习笔记

重新读了一遍《C程序设计语言》这本书,复习了一下C的基本语法,记录以备忘。
重要基础知识点:
在C语言中,所有的函数参数都是“通过值”传递的。
如果是数组参数,传递的是数组的起始地址,并不复制数组元素本身。在被调用函数中,可以通过下标访问或者修改数组元素的值

引用和取地址的区别:
引用&就像一个“修饰”一样,只有在定义和声明或者说明参数类型的时候才用,平时引用变量和普通变量一样。比如:
int& b;//只是说明作用,像一个 别名
b=10;
取地址符号是一个“动作”,比如:
int y = 10;
int *x = &y;//这里是取y的地址
需要注意的是,标准C语言并不支持引用,引用是C++里的概念。

外部变量和局部变量
函数内部的变量是自动变量(随着函数的退出自动销毁),也叫做局部变量,如果没有初始化则存放的是无效值,不会自动初始化。
所有函数外部的变量是外部变量,所有函数都可以访问,所以函数间可以通过这种方式交换数据。外部变量可以通过extern关键字声明,也可以隐式声明,如果外部变量的定义出现在使用它的函数之前,则函数中的变量声明就没有必要使用extern关键字。或者外部变量的使用与定义不再同一个文件中时,使用该变量的文件中必须加上extern。

定义和声明
声明:说明变量的性质,并不分配存储单元
定义:表示创建变量或分配存储空间

C语言只提供下面几种基本数据类型
char 1个字节 int  float double 
限定符:short(通常为16位)  long(通常为32位)    用于限定int型
类型限定符:signed unsigned 
long double高精度浮点数

静态变量
用static声明的外部变量或函数,可以将其后声明的对象的作用于限定在定义的源文件的剩余部分。
通常情况下,函数名是全局可访问的,用static声明的函数只能对同一个文件中的其他函数可见。
static修饰局部变量时,仍然是只能在函数内部访问,但是它不在随函数的退出而销毁,而是一直占用内存空间。
寄存器变量
register声明告诉编译器,它声明的变量在程序中使用频率很高,只用于声明自动变量及函数的形式参数。寄存器变量的地址不能访问。

初始化
在不进行显示初始化的情况下,外部变量和静态变量都将被初始话为0,自动变量和寄存器变量的初值没有意义。

预处理指令:预处理过程中执行
#include:编译期间将指定文件的内容包含进当前文件中(用“”引起来的文件,一般是用户自定义文件的包含;用<>引起来的文件,一般是库文件的包含)
#define 名字 替换文本:用任意字符序列代替一个标记(宏替换:直接将替换文本插入到代码中,可以避免函数调用所需的时间开销
#undef :取消名字的宏定义,这样可以保证后序的调用的函数调用而不是宏调用
条件包含:#if对其后的表达式进行计算,如果为0,则不包含后面的各行,直到遇到#endif,#elif,#else语句为止;否则包含后面的各行
#if后面可以用defined(名字)表达式,如果defined中的名字已经定义,则值为1,否则为0.例子:
#if  !defined(HDF)
#define HDF
/*hdf.h文件的内容*/
#endif
或者是如下形式:
#ifndef HDF
#define HDF
/*hdf.h文件的内容*/
#endif

指针
指针是一种保存变量地址的变量,大小一般是2个或4个字节,跟机器的可寻址范围有关
*:是一个间接寻址的运算符,可以访问一个地址变量指向的数据。
int *ip;     //*ip的结果是int型
ip=&c;     //ip是保存c的地址的变量,所以ip是个指针
*void是通用指针,可以指向任何类型的数据;其他指针只能指向某一特定类型的对象
 *和++等所有的一元运算符优先级相同,遵循从右向左的结合顺序。
  • *p++:表示对地址p+1运算后取值
  • (*p)++:对p指向的数据+1运算,相当于 ++*p
  • *s++ = *p++:因为是后加运算,所以赋值使用自增之前的值
  • 自增和自减作为前缀和后缀的区别:前缀是先自增,然后使用;后缀是先使用然后自增。
通过数组下标能完成的任何操作都可以通过指针来实现,一般来说,用指针编写的程序比用数组下标编写的程序执行速度块。
C语言保证,0永远不是有效的数据地址,但是可以赋值给指针,相当于null
size_t是由sizeof()返回的无符号整形

字符串常量
字符串常量的定义要点:
     * 类型是char[]
     * 连续存储,末尾自动添加\0
     * 静态存储
     * 相同值常量的地址可以不同
     * 修改字符是未定义行为
指针与数组
char amessage[]="now is the time";//存放初始化字符串和'\0'的数组,数组内容可以改变,地址不变
char *pmessage="now is the time";//pmessage初值指向字符串常量,可以修改指向其他地址,字符串常量不可写;所以比较好的习惯是写成:const  char *pmessage="now is the time";

指针数组:
如: char *lineptr[13];
理解方式一:是数组,数组中存放的是指针,
lineptr是一个有13个元素的数组,每个数组中是一个指向char类型的指针,即lineptr[i]是一个字符指针,*lineptr[i]是该指针指向的数组第i个元素的首字符
理解方式二:指向指针的指针
lineptr是一个指向一维数组的指针,一维数组中每个元素都是一个指向char类型的指针,通过*(lineptr+i)访问第i个字符串

数组指针:是指针,指针指向的数据类型是数组,相当于确定二维数组的列数,如:
int daytab[][13]<=>int (*daytab)[13]; //daytab是一个指针,指向具有13个整型元素的一维数组。 []的优先级大于*,所以要加()

二维数组与指针数组的区别
int a[10][20];
int *b[10];             优点:数组每一行长度可以不同
  • a是一个数组,该定义会给a分配200个存储空间
  • b的定义仅仅分配了10个指针,需要显式初始化;若初始化中b的每个元素指向一个具有20个元素的数组,则需要分配200个int型的存储空间和10个指针的存储空间
命令行参数
main函数中有两个参数:argc(参数的个数,包括函数名称) argv(指向参数数组的指针)
函数指针
函数的名字表示函数所在的地址
结构
结构是值传递的,在函数内部改变结构的属性值,原结构不变
结构的声明struct point{}; 大括号后面一定要加;号
结构指针:struct point *pp; pp表示指向结构体的指针
(*pp).x《=》pp->x表示结构体成员,注意"."操作符优先级高于* ,所以要加括号
所有运算符中,”.“、”->“、”()“、”[]“优先级最高
自引用结构
struct tnode{
     char *word;
     struct tnode *left;
     struct tnode *right;
}
一个包含其自身实例的结构是非法的,但是可以包含对自身实例的引用,所以上面的递归声明是正确的。
 typedef int length;建立新的数据类型














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值