C语言基础知识和注意事项

1.数组作为函数的参数会默认转换为指针,形参接收到的是数组的首地址。如果是字符数组作为参数,必须同时吧数组的长度传过去;如果是字符串,则可以不传长度,字符串有'\0'结尾,可以计算出字符串的长度;

2.static修饰的静态常量只能在当前文件中使用,全局变量可以在整个文件中使用,通过extern声明。extern不能和static一起用。

3.n级指针,就有n个*,n级指针的值 = n个*加指针变量名。二级指针存的是一级指针的地址(也就是二级指针取值= 一级指针的地址)。

4.字符数组表示字符串,如果这样写:char arr[]={'a','b','c',0}要么数组中有0或者‘\0’,否则会有有一堆不认识的字符出现,直到遇到 ‘\0’才结束;如果指定了数组长度,数组中可以不加0或者‘\0’.

5.指针的大小是4个字节。

6.字符串是常量。当字符串赋值给两个不同的指针p1、p2时,p1,p2的地址是一样的,不能通过指针改变字符串中的字符。如果开辟一个堆空间的地址p3,然后把字符串strcpy到堆空间的地址,这时候就可以通过p3改变字符串中的字符。

7.数组名是常量, 也是地址。

8.当一个吧一个数组arr赋值给指针p时,例如int *p=arr;如果操作了p++,p就取了arr中的第二个值,*p=30;这时候是改变的数组中第二个值。

9.字符串处理函数:

scanf()-------接受输入的字符串

gets()----从标准输入读取字符,存入指定的空间,知道出现换行符或者结尾。

puts()----输出字符;

strlen()---获取字符串有效字符的长度,不包含结束符'\0';

strcpy()------把src指向的字符串复制到desc中,'\0'也会复制过去。

strcat()---将字符串追加到目标字符串的结尾,'\0'也会追加过去。 

strcmp()-----比较两个字符串的ascii码值。

sprintf(buf,"%d%f%s\n",2,2.0,"ss")---格式化后存储到buf(字符串)中,也就是格式化字符串到指定的缓冲区

sscanf()-----格式化读取,格式化接收。

strchr()-----在字符串s中搜索字符c的位置,从c的位置开始往后取出字符串。

strstr()-----字符串中搜索字符串;

strtok()----切割字符串,切割点会变为'\0',得到切割字符之前的内容;切割后原来的字符串会破坏掉;

atoi()------字符串转换为int类型;

10.一个汉字占两个字节

11.内存操作函数:

memset()-----内存重置函数;

memcpy()-----拷贝内存中的数据;

12.结构体需要根据内存大小(以最大的)进行内存对齐。结构体的大小一定是最大结构体成员的整数倍。
13.结构体中的成员如果有数组,在输入的时候要给数组的每个元素挨个赋值。
14.注意下面这种字符串赋值要用strcpy,不能直接赋值。

15.结构体作为函数参数是值传递,结构体指针作为函数参数是引用传递。
16.结构体作为返回值正常可以返回值。结构体指针作为返回值可能会出错。
17.结构体可以嵌套结构体;

18.共用体的大小取决于成员中最大基本数据类型的大小,然后再看所有成员中最大数据的大小,取最大基本数据类型的整数倍。
19.共用体共用一块区域。共用体中最后一次赋值是准确的,之前赋值的都不准。


20.文件:磁盘文件、设备文件
                文本文件、二进制文件
21.文件操作的相关方法:

fopen()------打开文件,成功返回,失败返回NULL。
fputc()-----将一个字符写入到文件中
fgetc()-----读取文件中的字符;在读取文件中的字符时,文件中的光标是(根据读取的字符)自动变得
fclose()------关闭文件
文件中字符结尾标志EOF,就是-1。

feo(文件指针)------判断文件流是否到结尾。返回非0表示到文件结尾,0表示没有到文件结尾。

fgets()-----读取流文件,直到出现文件换行、文件结尾、读取字符的size-1,结尾自动加上\0;保存的地址的空间大于读取的数据,会加入\n\0;如果相等则只加入\0;   成功返回读取的字符串,错误返回NULL。可以是整行读取,也可以是一行分几次读取。

fputs()-----文件行写。-写字符串到文件中,字符串结束符\0不写入文件。

fprintf()--------往文件中格式化写入;

fscanf()--------从文件中格式化读取;

fwrite()-----以二进制的形式写进文件。

fread()-----从文件中读取二进制。

22.一般在输入的时候遇到空格和回车换行\n就会停止接收输入。
       接收字符串允许空格的两种写法:scanf("%[^\n]",buf);fgets();

        getchar()------可以接收任何字符,空格、换行。

  23.注意:     char s2[10]; ------>在C语言中这样定义之后s2就成为指向数组首元素的常量指针 
        s2 = "China";------>对常量赋值当然不可以 

23.栈中的变量不需要我们管理,程序结束或者作用于结束自动销毁。堆中开辟的空间要手动free。

24.fflush()-----更新缓冲区。

25.随机数:

srand((unsign int)time(NULL))-------随机数种子。

rand()%3--------获取取随机数0-2

结构体需要根据内存大小(以最大的)进行内存对齐。结构体的大小一定是最大结构体成员的整数倍。
结构体中的成员如果有数组,在输入的时候要给数组的每个元素挨个赋值。
结构体中的字符串赋值要用strcpy,不能直接赋值。

结构体作为函数参数是值传递,结构体指针作为函数参数是引用传递。
结构体作为返回值正常可以返回值。结构体指针作为返回值可能会出错。
结构体可以嵌套结构体;

共用体的大小取决于成员中最大基本数据类型的大小,然后再看所有成员中最大数据的大小,取最大基本数据类型的整数倍。
共用体共用一块区域。共用体中最后一次赋值是准确的,之前赋值的都不准。


文件:磁盘文件、设备文件
文本文件、二进制文件
fopen()------打开文件,成功返回,失败返回NULL。
fputc()-----将一个字符写入到文件中
fgetc()-----读取文件中的字符
fclose()------关闭文件
remove()---删除文件
rename()----重命名,或者移动
fflush()----刷新缓冲区,让缓冲区的内容立马写到文件中去。如果不刷新,只有等文件关闭后才会把缓冲区中的内容写入文件中

文件结尾标志EOF,就是-1。

getchar()------可以接收换行。
一般在输入的时候遇到空格和回车换行\n就会停止接收输入。
接收字符串允许空格的两种写法:scanf("%[^\n]",buf);fgets();

大文件拷贝
stat()----获取文件的状态。
fread()----以二进制读取文件,返回的是读取成功的块数或者是读取整块之后的余数
fwrite()----以二进制写入文件,返回的是写入成功的块数
ftell()--------查询当前光标位置
rewind()----把光标移动到文件开头


_popen()----操作command命令行打开或者创建文件
_pclose()----命令行关闭文件

char *p1,p2;注意p1是char *类型,p2是char类型。
char *p1,*p2;两个类型都是char*。
void不能直接定义变量,因为编译器不知道分配多少内存;当定义一个变量,编译器必须要知道分配多少内存,否则报错。
void*可以定义变量;Viod*是所有指针的祖宗,任何类型的指针不经过强转,就可以转换成void*类型;void* 主要用于数据结构的封装。
void可以作为函数返回值和参数。
sizeof返回的是某一数据或类型在内存中分配的空间大小,以字节为单位。以分配的空间大小为准,而不是实际使用的空间大小。
sizeof返回的数据类型是unsigned int类型。
注意:和unsinged类型的数据一起运算,大部分编译器返回的结果也是unsigned类型,也就是不为负数。
结构体的大小的计算跟不同的对齐模式有关系。
数组作为函数参数会退化为指向数组首元素的指针。

代码区是只读的,共享的,
初始化的静态变量和全局变量,常量-----data区    
静态变量只能在当前类使用,
字符串是常量,数组名是常量,const修饰的全局变量是常量区,,一旦定义不能修改,直接和间接都不能修改。
const 修饰局部变量是在栈区,不能直接修改,可以间接修改值;

未初始化的变量----bss

注意不要在函数中返回局部变量,函数结束就回收了;

局部变量---栈区
函数在栈区。
注意栈底部是高地址,
函数运算的结果有时候先放到寄存器,有时候放到栈中。
栈的存储方向从高地址到地地址。

内存的存储方向:小端模式---------高位字节放在高地址,地位字节放在地地址,(0xaabbccdd中aa是高字节,放在高地址,dd是低字节放在低地址)
大端模式------高位字节放在低地址,低位字节放在高位地址。

函名也是一个地址。
函数的形参也是局部变量,和实参不是同一个。
全局静态变量和局部静态变量都存在静态区,生命周期是程序运行期间;
局部静态变量的使用仅仅限于当前函数内部,全局静态变量的使用范围从定义到文件结尾。
extern 外部文件可以使用,告诉编译器变量是存在的,先通过编译,然后连接器去找变量。
头文件中只放申明,不要放定义,external inta;
static 只能在当前文件使用。
程序编译的时候.h是不编译的。
字符串常量的修改在c99标准并没有规定,有些编译器可以修改字符串常量,有些不能修改,有些编译器做了优化,所有的形同的字符串都
指向同一个,更改一个会导致其他使用的地方也受影响,所以不要修改字符串。
C语言的源文件是.c    C++的源文件是.cpp
一个.c 文件是一个编译单元,编译器独立编译每一个.c文件。

宏只是预处理器简单的文本替换。对于一般短小的函数和频繁使用的函数用宏,普通函数的调用有开销(函数压栈,跳转,,返回等)


指针--------------------------
不管几级指针,都占4个字节。
NULL本身是一个空指针:(void *)0.
指针的类型决定了步长,还决定解引用的时候从给定的地址开始取类型大小的字节数。
不同类型的指针之间是可以强转的。
数组名作为函数参数,就会退化为指向首元素的指针。

calloc在堆内存分配空间,会自动将分配的内存置为0;
realloc重新分配mallco或者callloc函数在堆中的内存空间大小,realloc不会自动清理增加的内存,需要手动清理,如果指定的地址
后面有连续的空间,那么就会在已有的地址基础上增加内存,如果指定的地址后面没有空间,那么realloc会重新分配新的连续空间,把
旧内存的值拷贝到新内存,同时释放旧内存。如果realloc的第一个参数为空就等价于malloc或calloc。


这两种情况数组名不是指向首元素的指针:sizeof,&arr时。除了以上两点都是指向首元素的指针。数组名是一个常量指针。

数组指针------指向数组名的指针,并不是指向数组的首地址,数组名是指向元素首地址;
指针数组------元素是指针的数组;
二维数组可以用数组指针表示;

结构体指针------指向结构体的指针;
结构体的拷贝是内部逐个拷贝;如果结构体内部有堆空间赋值的话,就不能用编译器赋值(会造成内存泄漏,同一个堆内存释放两次会报错),要手动赋值。

猜你喜欢

转载自blog.csdn.net/u011146511/article/details/84874611