c语言基础知识
一、常量变量
1.常见的一些数据类型
int 4字节,short 2字节,long 4字节(跟平台有关,可能是4,也可能是8),longlong 8字节, char 1字节,float 4字节,double 8字节
2.字符串
是由双引号引起来的一串字符,以/0作为结束标志。
‘/0’不是字符串的内容,只是一个结束标志,所以strlen时不会求‘\0’的长度
char arr[] = {'h','e','h','e'};
printf("%s", arr); //%s是以字符串形式输出,遇到‘/0’停止,但是arr[]数组中没有‘/0’,所以就会继续访问后面的内容,知道遇到‘/0’为止,所以会访问内存出错
3.const关键字
- 在c语言中:当const修饰一个标识符的时候,这各标识符依然是一个变量,只是具有常属性,不能被直接改变
- 在C++中,const修饰一个标识符时,编译器会自动将其设置未寄存器变量,当使用指针取修改时,改的时内存里面的值,所以寄存器中存储的值仍然不会被改变
const int sz = 10;
int * p = (int*)&sz;
*p = 20;
printf("%d", sz); //10
volatile const int sz = 10;
int * p = (int*)&sz;
*p = 20;
printf("%d", sz);//20
volatile:保证内存的可见性,让变量的每次取值都去内存里去取,这样就可以改变sz的值了
4.define:是一个指令,并不是一个关键字
#define PAI 3.14
5.枚举:enum关键字,枚举常量的值会依次增加,如果不指定就从0开始加,如果指定,就从指定值开始增加
enum Sex
{
MALE,
FEMALE,
SECRET
};
enum Sex
{
MALE=20,
FEMALE,
SECRET
};
6.register关键字:会将变量存储在寄存器内,不能对其进行&操作,因为编址是针对内存的。register只是一个建议。
7.fflush(stdin)/fflush(stdout):清空输入输出缓冲区
8.static关键字:
局部变量:改变其生命周期(存储位置:栈->静态区)
全局变量:改变其链接属性(作用域)
9.初始化:
全局变量:默认初始化为0
局部变量:必须自己初始化(随机值)
10:printf()函数返回值:返回打印字符的个数
int i = 43;
printf("%d", printf("%d", printf("%d", i)));
i是43,其返回值是2,外层printf()输出的值为2,输出2后返回值为1,所以最外层的printf()返回1,即4321;
二、分支语句
1.if语句:else语句总是跟在其之前未配对的最近的if匹配
if语句书写规范:
- bool和零值比较:if(flag),if(!flag),不能使用if(flag==TRUE)/if(flag==FALSE),flag是个整数,可以被赋值为2,3,等如何非0数字来表示真,而TRUE,FLASE只有一个固定的值
- 整形变量和零值比较:if(n==0),if(n!=0)
- 指针变量和零值比较:if(p==NULL),if(p!=NULL)
- 指针使用时要注意:1.初始化为NULL 2.使用之前判空
int *p = NULL;
if (p != NULL)
{
*p = 20;
}
- 浮点数与零值比较:#define EXP 0.0000000001 ,if((f>-EXP)&&(f<EXP))
2.switch语句:switch,case语句中,case后必须为整形的常量表达式。
switch语句中,我们没有办法实现分支,搭配break才能实现真正的分支。
最好在最后加上default语句,甚至可以在后边也加一个break
三、循环语句
1.break与continue:
whlie语句中:break:永久跳出循环,continue:终止本次循环,跳到while语句的判断部分
for语句中:break:永久跳出循环,continue:跳出循环体,到调整部分
2.while语句:
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d", i);
i = i + 1;
}
//输出1 2 3 4
int i = 1;
while (i <= 10)
{
if (i == 5)
continue;
printf("%d", i);
i = i + 1;
}
//输出1 2 3 4 在i=i+1,之前就跳出循环了所以i一直为5,然后陷入死循环
int i = 1;
while (i <= 10)
{
i = i + 1;
if (i == 5)
continue;
printf("%d", i);
}
//输出 2 3 4 6 7 8 9 10 11,没有5
3.for循环的一些变形
int i = 0;
int j = 0;
for (; i < 10; i++)
{
for (; j < 10; j++)
{
printf("hehe\n");
}
}
//输出10个“hehe”,i=0进入循环直到j=10,共十次,下次i=1进来时,j=10不进入循环
注:编程时要特别注意不要将==误写为=;
for (i=0,j=0; i < 2,j<5; i++,j++)
{
printf("hehe\n");
}
//输出5个“hehe”,i<2,j<5;是一个逗号表达式,逗号表达式从左向右求值,结果为最后一个表达式的值
for (i = 0, j = -1; j = 0; i++, j++)
{
j++;
printf("hehe\n");
}
//不输出,k=0,给k赋值为0,0为假,不进入循环
for (;;)
{
printf("hehe\n");}
//判断条件为空,默认为真,陷入死循环
for (i=0,j=0;i+j<10;++i,j++)
{
printf("hehe\n");
}
//输出五个hehe
4.循环效率
在多重循环中,如果有可能,要将最长的循环放在内层,最短的循环放在外层,以减少CPU跨切循环层的次数
循环体内部存在逻辑判断,并且次数很大的,宜将逻辑判断放在循环体外面
四、操作符与表达式
1.算术操作符:+ - * % (只能用于俩个整数)/(可用于整数与浮点数)
2.位移操作符:
左移:末尾补零
右移:逻辑右移:补零,算术右移:补符号位
3.位操作符:&:按位与,|:按位或,^:按位异或(俩个相同的数字异或结果为0,不同为1)
注:他们的操纵数必须时整数
4.单目操作符:sizeof(以字节为单位,不是关键字) &:取地址
5.sizeof使用注意事项:
int a = 10;
printf("%d",sizeof(a));
printf("%d", sizeof a);
//printf("%d", sizeof int);
printf("%d", sizeof(int));
注:sizeof在求变量所占空间大小时,用变量名可以去掉(),用类型时,不能去掉(),但是我们建议不去掉()
int a = 1;
short s = 3;
printf("%d\n", sizeof(s = a + 5));
printf("%d\n", sizeof(s));
printf("%d\n", s);
注:sizeof内部的表达式不参与运算
6.数组名单独放在sizeof内部表示整个数组;&数组名:表示整个数组
7.逻辑操作符:
&&:逻辑与,俩边有一个为假,则表达式结果为假,若左边为假,后面的即不参与运算
||:逻辑或,俩边有一个为真即为真,若左边为真,后面的即不参与运算
例:
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++&&++b&&d++;
printf("a=%d,b=%d,c=%d,c=%d", a, b, c, d);
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++||++b||d++;
printf("a=%d,b=%d,c=%d,c=%d", a, b, c, d);
8.三目操作符: exp1?exp2:exp3
找俩个数里大的一个
int a = 10;
int b = 20;
int i = a > b ? a : b;
printf("%d", i);
9.逗号表达式:从左向右求值,整个表达式的结果为最后一个表达式的结果
10.表达式的求值结果有三个影响因素:
1)操作符的优先级
2)操作符的结核性
3)是否控制求值顺序
五、函数
1.传参:
值传递:形参是实参的一份临时拷贝,形参和实参分别占有不同的内存块,对形参的修改不会影响实参
传址:形参和实参依然占有并不太的存储空间,但是俩者直接有一层联系,形参里存放的是实参的地址,这样就可以通过对形参的间接访问操作实参。
2.链接属性:在程序链接时起作用
1)外部链接属性:全局标识符具有外部链接属性,外部链接属性意味着,一个标识符,不仅可以在当前源文件使用,使用exetrn的声明也可以在其他源文件使用
2)内部链接属性:只能在当前源文件内使用,具有外部链接属性的标识符加上一个static关键词修饰就会变成内部链接属性
static:修饰变量:全局——改变链接属性(外部链接属性->内部链接属性)
局部——改变存储位置——从而改变生命周期
修饰函数:链接属性(外->内)
3)无属性(局部变量,出了作用域即失效,所以无链接属性)
六、数组
1.数组是一组相同类型元素的集合,数组创建时[]内必须是一个常量,不是使用变量
2.数组创建时,如果不想指定数组的大小,就得初始化,数组的元素个数根据初始化的内容定下来
3.数组名代表数组首元素的地址
char arr1[] = "abcdef";
char arr2[] = "abcdef";
if (arr1 == arr2)
printf("hehe\n");
//数组名代表首元素的地址,俩个数组中“abcdef”的地址不同,所以不输出
char *p1 = "abcdef";
char *p2 = "abcdef";
if (p1 == p2)
printf("hehe\n");
//输出hehe,p1和p2指向同一块地址
4.数组的使用:
int *p = arr;
&arr[i] <==> p+i <==> p[i]
arr[i] <==> *(p+i) <==>*(arr+i)
5.指针:可以理解为一个变量,时一个专门用来存放地址的变量
在32位平台下时4字节,64位平台下8字节
上一篇: C语言数组总结
下一篇: Java数组进行初始化