ps:接上一篇,本篇继续先讲操作符。
4.条件操作符(三目操作符)
注:不建议去嵌套使用,使其变得复杂。
exp1 ? exp2 : exp3 这里的exp是表达式
exp条件成立吗?成立为exp2,不成立为exp3。
举例:
#include <stdio.h> int main() { int a = 1; int b = 3; int m = (a > b ? a : b); printf("%d\n", m);//打印出来就是b的值3 return 0; }
5.逗号表达式
exp1, exp2, exp3, …… expN
特点:表达式从左到右依次进行计算,但是整个表达式结果是最后一个表达式的结果。
举例:
#include <stdio.h> int main() { int a = 1; int b = 2; int c = 3; int res = (a = a + 1, b = b + a, c = c + b); printf("%d\n", res);//打印出来是res为7 return 0; }
6.[ ] - 下标访问操作符,()- 函数调用操作符
举例:
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; 打印数字3。
#include <stdio.h> int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};//这里的[]是创建时的一个语法,不是操作符 printf("%d\n", arr[2]);//注:这里的arr和2是[]的操作数 return 0; } #include <stdio.h> int Add(int x, int y) { return x + y; } int main() { int a = 1; int b = 2; int res = Add(a, b);//这里的()就是函数调用操作符。Add,a,b是函数操作数 printf("%d\n", res); return 0; }
本篇新开内容从下面一行开始。
1、常见关键字
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
由于本人能力有限,这里给大家列举一部分。
1.1 auto关键字
在局部变量之前用,因为局部变量就是自动变量,可以省略,一般不写。
举例:
#include <stdio.h> int main() { auto int a = 10;//局部变量,在局部范围里自动创建,自动销毁 return 0; }
1.2 break关键字
在循环语句,switch语句中使用,意为终止。
1.3 typedef关键字:类型重命名 - 别名
如果定义变量名太长,使用它可以将名字改的短一点,要是大量使用就可以变得简单一些
举例:
#include <stdio.h> typedef unsigned int unit;//将unsigned int改为了unit int main() { unsigned int num = 100; unit num = 100; return 0; }
1.4 static关键字(静态的)
作用:(1)修饰局部变量。(2)修饰全局变量。(3)修饰函数
(1) 修饰局部变量:本质是存储位置发生变化,一个普通的局部变量是放在栈区的,而被static修饰的局部变量,是放在内存的静态区的,到了静态区,局部变量出了作用域不会销毁,影响了生命周期,但是作用域没有受影响。即修饰之后只创建一次,一直到程序结束被销毁。
举例:
#include <stdio.h> void test() { static int a = 1;//main函数在调用test函数打印时,循环10次都应该是2.但是用static修饰之后,每一次的a都被保存了下来,所以就实现了不断+1,打印出来是2~11。 a++; printf("%d ", a); } int main() { int i = 0; while(i < 10) { test(); i++; } return 0; }
(2) 修饰全局变量: static修饰全局变量这时全局变量的外部链接属性就变成了内部链接属性,只能在自己的.c文件中用,其他的.c文件那无法使用。
举例:
在Add.c文件中写的全局变量本来在test.c文件中声明外部符号就可以正常使用,但是用static修饰之后就不能使用了,限制了作用域。
(3)static修饰函数:static修饰外部函数这时外部函数的外部链接属性就变成了内部链接属性,只能在自己的.c文件中用,其他的.c文件那无法使用。
举例:
1.5 define 定义常量和宏
举例:
#include <stdio.h> //#define 常量和宏 #define M 100 #define STR "abcdef" #define MAX(x, y) ((x) > (y) ? (x) : (y)) //定义宏 运用三目操作符对传进来的数字进行比较 int main() { printf("%d\n", M);//这里打印结果就是100 printf("%s\n", STR);//打印结果就是abcdef int a = 10; int b = 20; int m = MAX(a, b);//调用define定义的宏,对a,b进行比较 printf("%d\n", m);//打印结果是20 return 0; }
2.指针
2.1 内存
2.1.1 一个内存单元多大比较合适呢?
电脑内存由小到大: TB -> GB -> MB -> KB -> byte(字节) -> bit(比特位)
1 byte = 8 bit , 1 KB =1024 byte
如果一个内存单元是bit太细,不合适,所以byte是最合适的,在创建char类型时最小也是一个字节,创建的时候char ch,正好是一个字节,所以使用字节最为合适.
举例:我们买快递的时候填写详细地址,***省***市***区***街道*号楼*单元***,这是很详细了,这里就相当于到字节.再详细不会到具体家里哪个房间哪一平米了,这就相当于比特位了,比特位最小了.
2.1.2 内存单元的编号怎么产生?
地址的产生:32位机器上,32根地址线(电线),电线是通过高电频,低电频 ,转化成数字信号 1 / 0(二进制),能组成2^32(4294967296)个二进制序列,也就可以管理2^32个内存空间.分别为:
00000000000000000000000000000000
00000000000000000000000000000001
...
...
...
11111111111111111111111111111110
11111111111111111111111111111111
这些就分别对应了一个内存单元.
2.1.3 代码举例指针
#include <stdio.h> int main() { int a = 10; int* pa = &a;//pa叫指针变量, & - 取地址操作符 printf("%d\n", a);//打印结果是10 *pa = 20;//* - 解引用操作符 printf("%d\n", a);//打印结果是20 printf("%d\n", *pa);//和上面一行是一样的意思 return 0; }
注:* 说明pa是指针变量,int 说明pa指向对象是int类型的,& -- 取地址操作符, * -- 解引用操作符(pa存放了地址,用 * 可以找出来a)。
2.1.3.(1)
打印地址:用 %p
举例:
#include <stdio.h> int main() { int a = 10;//向内存申请4个空间存储10 printf("%p\n", &a);//& - 取地址符,&a 实际占用4个字节的空间,每个字节都有空间,但是&a拿到的是第一字节的地址(也就是小的地址) return 0; }
2.1.3.(2)
指针变量的大小是多大?
指针变量是用来存放地址的。
地址是:
32位机器上:32个0/1组成的二进制序列,需要32bit位的空间存储,指针变量就需要4个字节。
64位机器上:64个0/1组成的二进制序列,需要64bit位的空间存储,指针变量就需要8个字节。
举例:
#include <stdio.h> int main() { char* p1; int* p2; double* p3; printf("%d\n", sizeof(p1));// 4/8 printf("%d\n", sizeof(p2));// 4/8 printf("%d\n", sizeof(p3));// 4/8 printf("%d\n", sizeof(char*));// 4/8 printf("%d\n", sizeof(int*));// 4/8 printf("%d\n", sizeof(double*));// 4/8 //32位机器打印结果时4,64位机器打印结果就是8. return 0; }
3.结构体(struct)
结构体是C语言一个重要知识点,可以使C语言有能力描述复杂类型。
描述一个学生(名字 + 年龄 + 性别 + 学号)举例:
#include <stdio.h> //结构体类型 struct Student { char name[20];//名字 int age;//年龄 char id[15];//学号 float score;//成绩 }; int main() { //结构体对象 struct Student s1 = { "张三", 20, "21610108252698", 88.2f }; printf("%s %d %s %f\n", s1.name, s1.age, s1.id, s1.score); //用指针的方式写 struct Student* p = &s1; //用结构体变量.成员 方式打印 printf("%s %d %s %f\n", (*p).name, (*p).age, (*p).id, (*p).score); //用结构体指针->成员 方式打印(和上面打印结果是一样的) printf("%s %d %s %f\n", p->name, p->age, p->id, p->score); return 0; }
把结构体看成盖房子,结构体类型就像是图纸,按着图纸盖房子。