C语言小知识点(结合C primer plus)

        小白一枚。下面分享一些我在学习C语言时记的一些笔记,主要是C语言的一些语法和其他的基本知识点。希望大家多多批评指正。后续会继续跟新~ 

 


1.1byte(字节)=8bits(比特)[1B=8b]
   位:bit
   字节:byte
   字:计算机进行数据处理时,一次存取、加            工和传送的数据长度称为字(word)
   字长:字长:计算机的每个字所包含的位数称为字长。例如286微机的字由2个字节组成,它的字长为16;486微机的字由4个字节组成,它的字长为32位机。

2.计算机用补码来进行数值运算
   正数:原码=反码=补码
   负数:反码=原码符号位不变,其余位取反
           补码=原码符号位不变,其余位取反再     +1
3.(signed)int有4个字节,32位。
   数的范围:-2^31~2^31-1
      unsigned int有32位
   数的范围:0~2^32-1
4."stdio.h":standard input output.header
    标准输入输出头文件
5.实型(浮点型)常量,有俩种表达形式:十进制数形式和指数形式
   指数形式:2.1e2(=2.1✘10^2)

float小数点后保留6位有效数字
6.char类型实际上存储的是整数(ASCII码)而不是字符
    例如:char a=120;
            char b=121;(int b=121效果相同)
    以字符型(%c)输出x,y
    以整数型(%d)输出120,121
7.char占一个字节即8位。故char只能存放一个字符,不能存放字符串。
8.字符常量'a'的内存存放形式:[a]
    字符串常量"a"的内存存放形式:[a][\0]
字符串结束标志:最后一个字符为"\0"

类型转换(自动类型转换、强制类型转换)
9.自动类型转换
   char,short—int—unsigned—long(—float)—double
(1)若参与运算量的类型不同,则先转换成同一类型,然后进行运算。
(2)转换按数据长度增加(字节长)的方向进行,以保证精度不降低。若两种类型的字节数相同,且一种有符号,一种无符号,则转换成无符号类型
(3)所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。
(4)char型和short型参与运算时,必须先转换成int型。
(5)在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度比左边长时,将丢失一部分数据。
10.强制类型转换
    (类型说明符)(表达式)
11.无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
例:表达式(double)i的类型是double,而i的类型并没有改变,仍然是int

12.除法运算符"/"
     整数(int)运算 取整
     实型(float/double)参与运算,结果为double
13.运算符优先级
    初级运算符( )、[ ]、->、.  高于  单目运算符  高于  算数运算符(先乘除后加减)  高于  关系运算符  高于  逻辑运算符(不包括!)  高于  条件运算符  高于  赋值运算符  高于  逗号运算符
14.自增,自减
     i++,i先参与运算i的数值再增1(运算参加整个语句的运算;i++和i--的值和i一样)
     ++i,i的数值自增1赋值给i++
15.所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。
16.scanf

scanf函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。 
        ① 遇空格、“回车”、“跳格”键。 (除了%c,每次读取一个字符,跳过所有空白字符)
        ② 遇宽度结束。 
        ③ 遇非法输入。
scanf读取失败后,把无法读取的输入留在输入队列里,供下次读取

https://blog.csdn.net/xia7139/article/details/14522493?utm_source=app&app_version=4.11.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

17.printf
     %7.2f输出长度7,保留2位小数
     %6d :最小输出长度为6,长度大于6,全部输出,小于6,左边补空格
     %-6d :小于6,右边补空格
18.关系表达式
用关系运算符将俩个表达式连接起来的式子,称为关系表达式,反应了关系运算(比较)的结果,它是一个逻辑量,取值"真"和"假",用1和0表示。
例:int a=2,b=3,c=1
a>b==c 值为1

条件表达式
a?b:c 表示当a的值不为0的时候,表达式等于b,否则等于c
19.快捷键
      全选+alt+F8则系统会自动排序
20.while(表达式)
只要表达式为真,就会一直循环。不是只执行一次
例如:i=1,sum=0;
while(i<1000)
sum=sum+i;
i++;因为没有{}所以i++无效,将一直循环
21.getchar
它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了,第一次getchar()时,确实需要人工的输入,但是如果你输了多个字符,以后的getchar()再执行时就会直接从缓冲区中读取了。
实际上是 输入设备->内存缓冲区->getchar()
22.凡用while能实现的,for语句一定能实现
23.break只适用于循环语句和switch语句。/break用来跳出循环
break终止整个循环,continue结束本次循环
24.程序执行后闪一次退出
方法:在程序末+getchar()

28.数组的大小必须在程序运行前确定/不能在程序中临时输入数组大小


29.C语言程序过程:预处理,编译,汇编,运行
30.C语言,二维数组按行排列
int a[3][4]={{1},{2},{3}},初始化每一行第一个元素,其余为0
int a[3][4]={1,2,3},初始化第一行前三个元素

31.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。
形参的值改变并不会改变实参的值(子函数里对实参的操作在函数调用结束后并不会改变实参的值)
32.
数组作为函数参数时,实际上只传递数组首地址(数组退化为指针),数组元素本身不被复制。和声明定义的数组不同,可不指定大小且可以改变实参值

当字符数组名、字符串常量、或字符指针作为函数实参时,相应的形参都是字符指针,它也可以写成数组形式

按值传递时,函数不会访问当前调用的实参。函数处理的值是它本地的拷贝,这些拷贝被存储在运行栈中,因此改变这些值不会影响实参的值。一旦函数结束了,函数的活动记录将从栈中弹出,这些局部值也就消失了。
按址传递,传递的是两个变量的内存地址(指针),使得我们可以直接操作对应的值。

*数组元素和数组名作为形参区别
//应用:如果想在子函数中改变主函数中的局部变量(实参)的值,那么必须将该局部变量的地址传递到子函数里
//形参是地址,则可改变实参的值;形参是数值,不可改变实参的值
//数组元素作为形参,形参格式为(int a)
  数组名作为形参,形参格式为(int a[])


33.数组中元素地址是连续有序的,因此只需要将数组的首地址传递到子函数
34.实参求值顺序:从右向左
例如:int f(i-1,++i); 先计算++i,再计算i-1

34.形参格式只需要知道数据类型,不用明确数据长度。例:(int a[])

35.局部变量和全局变量(变量的作用域来分)
局部变量是在一个函数内部定义的变量,只在该函数内部有效。(例:形参和函数里定义的变量)
在函数外定义的变量为外部变量/全局变量
//主函数里的(局部)变量不能在子函数里使用
36.动态变量和静态变量(变量的生存期来分)
静态存储方式是程序开始后由系统分配固定的存储空间
动态存储方式是程序开始后根据需要进行动态的分配存储空间
变量存储类别:
自动的(auto);静态的(static);寄存器的(register);外部的(extern)

auto:
函数中的局部变量,如不专门声明为static存储类别都是动态的分配存储空间的(栈),数据存储在动态存储区

static:
局部变量的值在函数调用结束后不消失而保留原值,即所占用的存储单元不释放,在下一次函数调用时,该变量已有值

外部变量只限于本文件引用而不能被其他文件引用
(static可让一个局部变量变为静态变量,也可让一个全局变量捆绑在一个固定的文件里)

register:
将局部变量的值存储在CPU的寄存器(静态、动态存储都是存储在内存里)内,需要时直接从寄存器取出参加运算,不必到内存里读取。(由于对寄存器的存取速度远高于对内存的存取速度,因此可以提高执行效率),
离开函数,值就消失
extern:
外部变量即全局变量。extern在任意位置定义全局变量(通常在首部定义全局变量)

//extern在多文件的程序里,文件里的外部变量可以被其他文件引用 
例:file1里首部定义外部变量 int A
   file2里 extern A声明A在其他文件定义

static在多文件的程序里,文件里的外部变量不能被其他文件引用 

37.
*  取值操作符(取地址对应空间存放的值)
& 取址操作符
例:int *pointer
pointer是指针即地址(存放整形数据)
*pointer是取数据
&a是a的地址

38.二维数组a[m][n]
a:二维数组名,指向一维数组a[0],即0行首地址

a[0]、*(a+0)、*a: 0行0列地址

a+1、&a[1]:1行首地址

a[1]、*(a+1):1行0列a[1][0]地址

a[1]+2、*(a+1)+2、&a[1][2]:a[1][2]地址

*(a[1]+2)、*((a+1)+2)、a[1][2]:a[1][2]的值

//看见*,先转换为[]或者+

39.二维数组指针变量
类型说明符 (*指针变量名)[长度]
int (*p)[4]
长度:二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数
*(*(p+i)+j):i行j列数值

char string[][10]
={"ab","hhdg","hshhhyxy"}是二维数组
 
40.字符数组!=字符串
例:字符数组
char string[]={'h','e','l','l','o'};
==char string[5]={'h','e','l','l','o'};
字符串
char string[]={'h','e','l','l','o','\0'};
==char string[]="hello"
==char string[]={"hello"}
==char *string="hello"(字符串常量是一个值,该值是存放字符串首字符的地址)
==char string[6]={'h','e','l','l','o'};

字符数组的定义与初始化 
如果花括号中提供的字符个数大于数组长度,则按语法错误(error)处理;若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ),此时该字符数组为字符串。 
字符串数组可不定义长度
41.
'\0'是ASCII为0的字符,不是一个可以显示的字符,而是一个空操作符(转义字符null)。故用它来做字符串结束标志。其不会产生附加的操作或增加有效字符,只是一个供辨别的标志。
空格字符ASCII码为32
42.
字符数组输入输出
for(i=0;i<=n;i++)
scanf("%c",string[i]);
printf("%c",string[i]);

字符串输入输出
printf("%s",string);
puts(string);
whlie((a[i]=getchar()!='\0'))
i++;
(既输入字符串,又知有效长度)

从string地址开始到'\0'结束输出
scanf("%s",string);gets(string)

gets和scanf不同在于:
(1)scanf碰到缓冲区里面的空字符(空格,tab,回车换行)就会截断并添加\0,而gets是要等回车才截断字符串并添加\0的
(2)scanf不会舍弃最后的回车符(即回车符会残留在缓冲区内)
gets舍弃最后的回车符

比如用输入字符串:abcdefg hijk回车
用scanf的话,会得到abcdefg,而gets是 abcdefg hijk                  
//字符串输入有无空格(scanf gets)

puts和printf不同在于:
puts输出一个字符串后自动换行
printf不自动换行,需要\n

//一串还是一个 输入输出(%s%c)
  
43..若定义一个指针变量,并使它指向字符串,则可以用下标形式引用指针变量所指字符串里的字符
//只输出字符串里一个字符
例:char *a="hello"
printf("第二个元素:%c",a[1])

44.五大内存分区
http://bbs.fishc.com/home.php?mod=space&uid=9&do=blog&id=182

45..字符串数组和字符串指针变量区别
(1)
如果定义了一个字符数组,那么它有确定的内存地址。字符串复制到字符数组里;
而定义一个字符指针变量时,它并未指向某个确定的字符数据(如果定义时未初始化,就是个野指针),并且可以多次赋值。字符串存放在以该首地址为首的一块连续的内存空间中(常量内存区,不可改变)
例:char *a="hello" 不能对a[]进行修改
但! char a[]="hello"可以对a[]修改
(2)赋值方式
对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值
     char str[14];
     str="I love China";     
因为这样相当于给指针常量(字符数组是确定内存)str赋值,这是不成立的
(但在字符数组初始化时可以,即char str[14]="I love China";
方法:
char str[14];
strcpy(str,"I love China");
     而对字符指针变量,采用下面方法赋值:
     char* a;
     a="I love China";
     或者是 char* a="I love China";       都可以
(3)
另外,对于指针变量,不可以由输入的方式来完成指定的操作。如:
char *str;
scanf("%s",str);
上述操作是错误的。可以理解为在声明的时候没有确定具体地址,然后在scanf赋值的时候没有确定的地址自然无法找到放置字符串的地方。

//总结:字符数组名是地址常量;字符指针是变量

函数指针和指针函数
46.函数指针(指向函数的指针)
(1)初始化:类型名(*变量名)(参数类型表)
例:int (*p)(int,int)
(2)使用时机:子函数间相互调用,使用函数指针
例:double f1(int x,int y);
double f(int a,int b,double(*f2)(int,int))
int main{
int  j,k;
double (*f2)(int,int),result;//定义函数指针
result=f(j,k,f1)//直接把f1赋给形参f2
}
47.指针函数(返回指针(地址)的函数)
int *p(int,int)

48.const char *str 
常量指针可以改指向不能改值
char * const str
指针常量可以改值不能改指向
(const表示紧跟在const后的是常量,不可改变)

49.有关指针的数据类型的小结
int *p  p为指向整形数据的指针变量
int a[n] 定义整形数组a,他有n个元素
int *p[n] 定义指针数组p,他由n个指向整形数据的指针元素组成
//用于存储多个字符串,n为字符串最大个数
int (*p)[n]  p为二维数组,n为数组列数
//用于存储多个字符串,n为最大长度
int *p() p为带回一个指针的函数,该指针指向整形数据
//用于返回地址
int (*p)()p为指向函数的指针,该函数返回一个整形值
//用于子函数的相互调用
int **p p是一个指针变量,它指向一个指向整形数据的指针变量

50.宏定义define和关键字typedef区别
define是字符串代换,是在预编译处理完成的;
typedef是对类型说明符重新命名,是在编译时处理

51.对于带参数的宏定义,字符串内的形参要用括号括起来避免出错
例:#define f(y) (y)*(y)
k=f(a+1)相当于(a+1)*(a+1)
#define f(y) y*y
k=f(a+1)相当于 a+1*a+1

52.预编译处理
(1)文件包含 #include<>
(2)宏定义 #define
(3)条件编译 #ifdef #endif

53.文件包含里文件名用尖括号和双引号区别:
#include<>表示在包含文件目录查找文件(系统自带库文件)
#include""表示在当前的源文件目录(自己写的文件)查找,若没有才到包含目录查找

54.Source Files、Resource Files、Header Files区别
Source Files文件夹:放源程序(.cpp .c)
Resource Files文件夹:放程序里需要的资源文件,如图标,对话框,图片等。
Header Files文件夹:放头文件,自定义文件(.h)

头文件一般包含:宏定义,结构体定义,C库头文件


结构
 55.关键字struct和他后面的结构名一起组成一个新的数据类型名
例:struct student{
……
}s1,s2;
struct student是数据类型
s1,s2是结构变量

56.结构指针
struct student{
……
}s1,*p;
p=&s1;
结构指针作为函数参数,对应的实参是结构数组名
int score(struct student *p,int n);
pos=score(s1,n)

57.访问结构成员
s1.num=100;
(*p).num=100;
p->num=num

58.空类型 void ()万能类型

59.动态存储分配函数malloc()
函数原型:void * malloc(unsigned size)
功能:在内存的动态存储区分配一连续空间,长度为size。若申请成功,则返回指向所分配内存空间的起始地址的指针(void*)即通用指针。具体使用时,将malloc的返回值转换为特定指针类型
如:p=(int *)malloc(n*sizeof(int))

动态存储释放函数free()
函数原型:void free (void *ptr)
功能:释放由动态存储分配函数申请到的整块内存空间,ptr为指向要释放空间的首地址

60.
链表是一种动态存储分配的数据结构,由若干个同一结构类型的"结点"串接而成
(链表与数组不同:链表的各个数据类型不同;链表可以实时增减数据结点)
链表变量一般用指针head表示,用来存放链表首结点的地址,每个结点由数据部分和下一个结点的地址部分组成
例:struct student{
int num;
char name[20];
struct student *next;
}


新建链表:
struct student *stu()
{
struct student *head,*p1,*p2;
(创建新节点)
p2->next=p1
p2=p1   //*p2后移一个结点*//
//p1,p2只是一个存放结点地址的指针变量,不是固定的结点//
p1=(struct student*)malloc(sizeof(struct student *))
// p1指向新结点存储空间 //
……
return head;
}

链表打印
p=p->next(p后移一个结点)

链表删除
p2->next=p1->next(删除p1)
free(p1)


61.
一般创建链表我们都用typedef  struct
例:typedef struct student{
int score;
struct student*next;
}LinkList;
因为这样定义结构体变量时,我们就可以直接可以用LinkList  *a;定义结构体类型变量了。
(一般要求重新定义的类型名用大写)
62.
IDE
集成开发环境,用于提供程序开发环境的应用程序(Visual studio,Dev,Vc6.0……)

编译后的黑色界面——控制台
63.位远算是指进行二进制位的运算
位运算的操作数只能是整型或字符型的数据
位逻辑运算符规则:先将俩个操作数化为二进制数,然后按位运算
操作数的位运算不改变原操作数的值

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值