04
2019
09

c语言基础复习笔记

  1. 每一个c源程序都必须有,且只能有一个主函数(main函数)

  2. 符号常量:一般形式为:#define 标识符 常量

其中#define也是一条预处理命令(预处理命令都是以#开头),称为宏定义命令,其功能是把该标识符定义为其后的常量值

3.字符值是以ASCLL码的形式存放在变量的内存单元之中的。

4.字符常量占一个字节的内存空间。字符串常量占的内存字节数等于字符串中字节数加1.增加的一个字节中存放字符“\o”(ASCLL码为0)。这是字符串结束的标志。

5.char型和short型参与运算时,必须先转换成int型。

6.所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。        char型和short型参与运算时,必须先转换成int型

7.\的意思就是把下一行当作是上一行的延续

eg:int main(){

print\

f("");

return 0;

}就等于

int main(){

printf("");

return 0;

}

\的这个作用也可以用在字符串里面

变量

8.变量的意义就是确定目标并提供存放的空间

9.变量命名第一个字母必须是字母或者下划线开头,不能使用关键字来命名变量

取值范围

10.int在默认情况下是带符号的,signed型,说明最高位是符号位

11.无符号int型即unsigned int 型打印的时候要用%u

12.事实上计算机是用补码的形式来存放整数的值

算术运算符

13,一个浮点型的结果,强行用整形%d打印出来就会乱码

捕获.PNG

逻辑运算符

14.短路求值又称最小化求值,是一种逻辑运算符的求值策略。只有当第一个运算数的值无法确定逻辑运算的结果时,才对第二个运算数进行求值,c语言对于逻辑与和逻辑或采用短路求值的方式

捕获.PNG

捕获.PNG

数组

14.数组中未被赋值的元素自动初始化为0

15.如果数组只是被定义,没有初始化,那数组里面的元素就是一堆乱的数字

16.c99增加了一种新特性:指定初始化的元素。这样就可以只对数组中的某些指定元素进行初始化赋值,而未被赋值的元素自动初始化为0

eg:int a[10]={[2]=2,[7]=8};

指针

17.指针都是4个字节,因为指针里面都是存放的地址,所以sizeof(指针)=4

18.%p是打印地址

19.数组名只是一个地址,而指针是一个左值

20.C 语言的术语 lvalue 指用于识别或定位一个存储位置的标识符。(注意:左值同时还必须是可改变的)

数组指针

21.eg:int (*p2)[5];

p2指向的是整个int数组

首先我们先来了解一下一个知识eg:

int temp[5]={1,2,3,4,5};

int (*p2)[5]=&temp;//temp是数组的第一个元素的地址,而&temp是整个数组的地址

int i;

for(i=0;i<5;i++){

     printf("%d\n",*(*p2+i));//p2指向的是整个数组的地址,而*p2指向的是第一个元素的地址

}

根据上面的代码做一下测试

#include<stdio.h>
int main(){
    int temp[5];
    int (*p2)[5]=&temp;
    printf("%p,%p\n",temp,p2);
    printf("%p,%p",temp+1,p2+1);
    return 0;
}

运行结果是

0060FF10,0060FF10
0060FF14,0060FF24请按任意键继续. . .

说明了什么呢?说明temp+1和p2+1的跨度不一样,p2+1就相当于二维数组的第二行,所以就不能 int (*p2)[5]=temp;

而上上面那个程序中的printf("%d\n",*(*p2+i));中的*(*p2+i))其实可以理解成*(*(p2+0)+i))

然后就明白了数组指针liao

指针和数组和二维数组

22.a[n] 表示 *(a+n),用 a[n][m] 表示 *(*(a+n)+m),

23.int a[5];&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。

24.

#include <stdio.h>
int main()
{
    int arry[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    printf("%d,%d\n", arry, *arry);                   //0行首地址         0行0列元素地址
    printf("%d,%d\n", arry[0], *(arry+0));            //0行0列元素地址     0行0列元素地址
    printf("%d,%d\n", &arry[0], &arry[0][0]);           //0行首地址        0行0列元素地址
    printf("%d,%d\n", arry[1], arry + 1);              //1行0列元素地址    1行首地址
    printf("%d,%d\n", &arry[1][0],*(arry + 1) + 0);      //1行0列元素地址    1行0列元素地址
    printf("%d,%d\n", arry[2], *(arry + 2));          //2行0列元素地址    2行0列元素地址
    printf("%d,%d\n", &arry[2], arry + 2);            //2行首地址           2行首地址
    printf("%d,%d\n", arry[1][0], *(*(arry + 1) + 0));//1行0列元素的值    1行0列元素的值
    printf("%d,%d\n", *arry[2], *(*(arry + 2) + 0));  //2行0列元素的值    2行0列元素的值   
    return 0;
}
-214132016,-214132016
-214132016,-214132016
-214132016,-214132016
-214132000,-214132000
-214132000,-214132000
-214131984,-214131984
-214131984,-214131984
5,5
9,9

void指针和NULL指针

void指针我们把它称之为通用指针,就是可以指向任意类型的数据。也就是说,任意类型的指针都可以赋值给void指针
int num=1024;

int *pi=&num;

char *ps="FishC";

void *pv;

pv=pi;

printf("pi:%p,pv:%p\n",pi,pv);

pv=ps;

printf("p:%p,pv:%p\n",pi,pv");

25.当你还不清楚要将指针初始化为什么地址时,请将它初始化NULL;要不然它就是野指针

int *p1;//野指针

int *p2=NULL;//正确的

26.NULL和NUL的区别:

NULL用于指针和对象,指向一个不被使用的地址;而NUL(即'\0')表示字符串的结尾

const

27.int num=520;

conts int cnum =80;

conts int *p=&cnum;

其中p的值可以改变,而*p的值不可以改变,因为conts修饰是int,说明p指向的是一个不可以被修改的整形,即

p=num;//是正确的

*p=1024;//是错误的


如果是int * conts p=&cnum;//说明conts修饰的是p,所以指针p所指向的地址是不可以改变的,但是*p的值是可以改变的,即

p=num;//是错误

*p=1024;//是正确

数组作为函数参数时

28.函数的类型就看函数的返回值

288.函数声明的时候变量的名字可以不写

29.当数组作为函数参数时,实际上实参传的是一个地址给形参

void get_array(int b[10]);

void get_array(int b[10]){

printf("sizeof b: %d",sizeof(b));

}

int main(){

 int a[10]={1, 2, 3,4,5,6,7,8,9,0};

printf("sizeof a: %d\n",sizeof(a));

get_array(a);

return 0;

}

运行结果是

sizeof a: 40

sizeof b: 4//因为a传给形参只是一个地址,一个地址就是占4个字节

可变参数

va_list 、va_start、 va_arg、 va_end


通过一个例子来说明这几个的用法


#include<stdio.h>

#include<stdarg.h>//上面说到的类型va_list和三个宏va_start、 va_arg、 va_end必须包含的头文件

int sum(int n,...);

int sum(int n,...){

    int i,sum=0;

    va_list vap;//定义一个参数列表

    va_start(vap,n);//初始化参数列表,vap就是上面定义的参数列表,n就是函数的第一个参数#define va_start(list,param1)   ( list = //(va_list)&param1+ sizeof(param1) )

for(i=0;i<n;i++){

sum+=va_arg(vap,int);//获取参数列表的下一个参数,#define va_arg(list,mode)   ( (mode *) ( list += sizeof(mode) ) )[-1]

//}

va_end(vap);//清空va_list可变参数列表,参数列表访问完以后,参数列表指针与其他指针一样,必须收回,否则出现野指针。

//#define va_end(list) ( list = (va_list)0 )

return sum;

}

int main(){

int result;

result=sum(3,1,2,3);

printf("result=%d\n",result);

}

运行结果是result=6


另一个例子:

#include <stdio.h>
#include <stdarg.h>
void functestarg(int,...);
int main ()
{
functestarg(1,2,3,4,5,6,7,8,9,10,0);
return 0;
}
void functestarg(int a,...)
{
va_list argpointer;
va_start(argpointer, a);
int argument;
int count = 0;
while(0 != (argument = va_arg(argpointer, int)))
{

printf("parameter%d:%d\n",++count,argument);
}
}

运行结果:

parameter1:2
parameter2:3
parameter3:4
parameter4:5
parameter5:6
parameter6:7
parameter7:8
parameter8:9
parameter9:10

指针函数

1.#include<stdio.h>

char *getWord(char c);

char *getWord(char c){ //注意这里字符串返回用了字符指针,因为字符串返回的是第一个字母的地址(C语言约定俗//成的规则),之所以是这样是因为字符串有结束符

    switch(c){

        case'A':return "Apple";//还有这里要注意用的是return,而不是经常写的break。仔细想想这样写很明智

       case'B':return "Banana";

       case'C':return "Cat";

       case'D':return "Dog";

    default:return "None";

}

}

int main(){

    char input;

printf("请输入一个字母:");

scanf("%c",&input);

printf("%s\n",getWord(input));

return 0;

}

2.不要返回局部变量的指针

#include<stdio.h>

char *getWord(char c);

char *getWord(char c){

    char str1[]="Apple";

   char str2[]="Banana";

  char str3[]="Cat";

  char str4[]="Dog";

  char str5[]="None";

    switch(c){

        case'A':return str1 ;

       case'B':return str2 ;

       case'C':return str3;

       case'D':return str4;

    default:return str5;

}

}

int main(){

    char input;

printf("请输入一个字母:");

scanf("%c",&input);

printf("%s\n",getWord(input));

return 0;

}

运行会出现警告,但是运行错误

函数的局部变量是存放在栈里面的,函数结束,栈就销毁,所以返回局部变量就会出现错误,因为你返回的局部变量已经不存在了

函数指针

1.函数名就是地址,规定的

捕获.PNG

其中的int (*fp)(int);//是定义一个函数指针,fp是指向一个参数是int,返回值是int的函数


2.函数指针作为参数的例子:

捕获.PNG

3.函数指针作为返回值的例子

捕获.PNG捕获.PNG

其中的int (*select(char))(int,int);//因为这些符号都是有优先级和结合性的,看运算符的优先级和结合性表,所以从左到右,select是函数名,参数是char,然后我们把已知的去掉就剩下int (*)(int,int);,就发现原来select函数返回的是一个函数指针,这个函数指针指向带两个int参数,返回值是int的函数


« 上一篇 下一篇 »

评论列表:

1.xialibing  2019-09-07 00:02:24 回复该评论
你怎么这么厉害啊
2.访客  2019-09-05 00:13:50 回复该评论
w
3.访客  2019-09-05 00:02:48 回复该评论
you kai shi xue xi la

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。