类型转换
对于printf函数,任何比int类型小的数都会转换成int,而scanf()则不会,需要手动设置读取的数据类型 输入整数 scanf("%d",&a) 输入short类型scanf("%hd",&a)
逻辑运算符以及优先级
"!age<20" 解读 就是 age 小于20 再取反
int age =19; if(!age<20){ printf("age=19 >20 "); //正确输出 }else{ printf("age=19 <20"); }
逗号运算符 ,主要用于for循环中的条件多次运算
int b = (3 + 4, 5 + 6); printf("b = %d ", b); //输出 b = 11 int i, j; for (i = 0, j = 10; i < 1; i++) { printf("i = %d ", i); //输出 i = 0 printf("j = %d ", j); //输出 i = 10 }
函数: 单一出口原则
函数先后顺序:C编译器自上而下的解析代码!因此在调用函数前,需要在方法前定义或者声明函数
本地变量:函数每次运行都会产生独立的变量空间,在这个空间中是函数这次运行所独有的称作“本地变量”,函数参数也属于本地变量
C语言函数内部不能再次定义函数
函数原型的定义方式
void test1(void); //明确标识此函数不接收任何参数 void test2(); //参数未知,能接收任意函数,可能导致未知错误 void sum(int ,ini); //规范标识,明确标识该函数接收2个int类型的参数,参数名称可加可不加
sum(a,b); //逗号在函数调用的时候作为参数分割符 sum((a,b)); //加上了括号,那么逗号则是运算符,代表着只传递了一个参数给sum函数
//正例 函数只会再末尾处返回正确的值 int max(int a,int b) { int maxValue ; if(a>b) { maxValue = a; }else{ maxValue = b; } return maxValue; } //反例 if和else 都可能会是函返回结果 int max(int a,int b) { if(a>b) { return a; }else{ return b; } }
数组
C99之前,数组元素数量必须是确定的字面量,C99之后允许动态分配数组大小
一旦创建,不能改变其大小;数组在其内部依次排列,
数组作为参数时,函数内部不能用sizeof计算数组的长度
取址运算符“&”
获取变量的地址,它的操作数必须是变量,
地址值的长度取决于编译器,32位编译器为4个字节,64位则为8个字节
//数组与取址运算符
void testArray(){ int a[10]; printf("%p ",&a); //输出 000000000062FDF0 printf("%p ",a); //输出 000000000062FDF0 printf("%p ",&a[0]); //输出 000000000062FDF0 printf("%p ",&a[1]); //输出 000000000062FDF4 }
指针变量——标识一个变量的内存地址
void p1() { int a=7; //定义普通变量 a =7 int *p = &a; //定义指针变量 *p = 变量a的地址 *p=10; //将指针变量地址上的值 修改为10; printf("a=%d ",a); //输出 = 10 }
指针应用一:交换两个变量的值
指针应用二:当函数运算时会发生错误,使用函数返回值判断函数是否正确运行,而运行结果采用指针返回
//指针应用、获取函数执行状态, int divide(int a,int b,int *result) { int ret = 1; //定义函数状态值 if(b == 0 ) ret = 0; //除数为0时,标识函数运行出错,无法继续运行 else{ *result = a/b; //满足条件,执行运算,将结果存入指针中 } return ret; //返回函数的运行状态 }
指针 与 const
const修饰数组时,标识该数组内部的值为const 不能被修改
void testPointConst(){ //判断哪个被const的标识是 const在 *前面 还是在 *后面 , //只要*在const前面,那么就是该指针不可修改,否则 指针指向的值 不可通过该指针去修改 int i = 10; int b = 20; printf("i =%X ",&i); printf("b =%X ",&b); const int* p = &i; //标识这个i不能通过指针去修改,但指针本身可以进行运算 ,i也可以进行运算 int const * p0 = &i; //含义同上,写法区别 int const *p1 = &i; //含义同上,写法区别 int const* p2 = &i; //含义同上,写法区别 //------------分割线---------------------------- int *const p3 = &i; int * const p4 = &i; p0--; printf("*p0 =%d ",*p0); //输出 20 //*p = i++; //此处错误 assignment of read-only location '*p' //p3++; //此处错误 increment of read-only variable 'p3' //p4++; //此处错误 increment of read-only variable 'p4' i++; printf("*p =%d ",*p); //输出 11 *p3 = 11; printf("p3 =%X ",p3); printf("p3-- =%X ",p3); printf("*p3 =%d ",*p3); }
指针的加法运算
//指针数组应用 void testPointArray(){ int a[10]; a[0] = 1; a[1] = 2; int *p = &a[0] ; printf("a[0] %X ",&a[0]); // 0x62fdf0 printf("a[1] %X ",&a[1]); // 0x62fdf4 printf("p = %X ",p); //0x62fdf0 p = p + 4; //指针做加法运算时,等于 (指针 加上 这个数 乘以指针类型的长度 ) printf("p+4 = %X ",p); //0x62fe00 *p = 10; printf("a[0] = %X ",a[0]); // 1 printf("a[1] = %d ",a[1]); //2 printf("a[4] = %d ",a[4]); //10 }
强制类型转换
//强制类型转换 void testPoint() { int a = 65536; //FFFF int类型为 4字节 二进制为 1000,0000,0000,000,,1111,1111,1111,1111 int* p = &a; short* p1 = (short*)p; //强转为short后 只读取 16位数据 根据补码规则,所有*p1的值=0 printf("%d ", a); //输出 65536; printf("%d ", *p1); // 输出0; }
动态分配内存
//动态内存分配 void testMalloc() { //malloc 函数在 <stdlib.h>中定义 ,返回值为void*类型 //c99之前 动态内存分配 int number; int* a; int i; printf("输入数组大小 "); scanf("%d", &number); //读取一个整数 a = (int*)malloc(number * sizeof(int)); //向os请求分配 int类型 * number块连续的内存空间 ,该函数返回值为void* 因此强转成需要的int类型 a[1] = 2; //指针<->数组 存在转换性 a++; int c = *a; printf("c = %d", c); //输出2 free(a); //释放之前 申请的内存空间 }
字符串
以0(整数)结尾的一串字符,0是标识字符串的结束,但它不是字符串的一部分,计算字符串长度的时候不包含这个0,字符串以数组的方式存在,以数组或指针的方式访问(常用指针),string.h中定义了很多处理字符串的函数
字面量 “hello”会被编译器解析成一个数组放在某处,并且在数组末尾处添加‘ ’标识字符串结束,因此它的长度等于6; 可以用来初始化字符数组
两个相连的字符串编译器会将他们联系在一起
void testString() { char b = 'a'; char* s = "hello,world"; //指针s 初始化为指向一个字面量,历史原因编译器接收不带sonst的写法 但实际解析时 的s 是 const char* s //s[0] = 'b'; //因此不可以修改该字符数组 printf("%p ", b); printf("%p ", s); //字符串使用原则: //char s[] = "hello,world"; 若使用数组,那么这个字符串作为本地变量空间自动被回收 // char* s = "hello,world"; 若使用指针,不知道字符串在哪里,通常用于处理参数,动态分配空间时使用 // 字符串可以用 char*的方式表达,但char* 不是绝对的字符串,它的本意是指向字符的数组, //只有当它所指的字符结尾处带有结尾的'0'时,才能被确认为是字符串 //字符串输入输出 格式化 scanf("%s",str); printf("%s" ,str); //scanf()函数非安全,因为它不确定读入的字符串长度有多少; //安全使用: 在%和s之间 插入一个 确定读取的长度 如 scanf("%7s",str),标识这一次只读取7个字符,多余的字符将会被下次scanf时获取到 char buffer[100] = ""; // 这是一个空的字符串,buffer[0] = ‘ ’; char buffer1[] = ""; //相当于用""初始化了该字符串,它的长度只有1 //字符串数组 char a1[][10] = { "hello" }; //二维数组 ,标识数组中每一个元素的长度都是为 char[10] char* a[10]; //字符串数组,标识这个数组中有10个指针,指向不确定的位置 a[1] = "hello world "; a[2] = "hello c "; printf("%s ", a[1]); printf("%s ", a[2]); //getchar(int a) 获取一个字符 ,返回获取的个数 //putchar(int a) 输出一个字符, }
字符串函数
//字符串处理函数 void testStrFun() { //string.h C语言标准库携带的头文件 char str[] = "hello1"; char str1[] = "hello"; printf("str长度 = %lu ", strlen(str)); //输出5 printf("str长度 = %lu ", myLength(str)); //输出5 printf("str长度 sizeof= %lu ", sizeof(str)); //输出6 因为字符串末尾还有一个' ' printf("str的地址是=%p ", str); printf("str1的地址是=%p ", str1); printf("mycmp是否相等%d ", mycmp(str, str1)); //返回0 标识2个字符串相等 printf("是否相等%d ", strcmp(str, str1)); //返回0 标识2个字符串相等 //拷贝函数 strcpy(char *restrict dst,const char *restrict src) //将src的字符串拷贝到dst中 返回dst restrict标识src与dst不重叠(C99) char* dst = (char*)malloc(strlen(str) + 1); char* res = strcpy(dst, str); printf("res的地址是=%p ", res); printf("dst的地址是=%p ", dst); printf("%s ", res); printf("dst = %s ", dst); char* myDst = (char*)malloc(strlen(str) + 1); printf("myStrCpy = %s ", myStrCpy(myDst, str)); //字符串拼接 cahr * strcat(char* restrict s1,const char *restrict s2) //将字符串s2拷贝到s1的后面,拼接成一个长的字符串,返回s1 条件s1必须具有足够的空间 char* s2 = "world"; char s1[20] = "hello,"; strcat(s1, s2); printf("strcat = %s ", s1); //输出 hello,world // strcpy,strcat,strcmp,都是非安全函数,c语言标准库中也提供了其安全版本 //char * strncpy(char *restrict dst,const char *restrict src,size_t n) // n 标识最多拷贝n个字符 //char * strncat(char *restrict s1,const char *restrict s2,size_t n) // n 标识最多拼接n个字符 //char * strncmp(const char *s1,const char *restrict src,size_t n) // n 标识 比较指定个数的字符,例,n=3,只比较前三个 //字符串查找函数 //char * strchr(const char *s,int c); //从左边开始查找指定字符 返回NULL 标识未找到 //char * strrchr(const char *s,int c); //从右边开始 char s3[] = "helloworld"; char *ps3 = strchr(s3, 'l'); //小技巧 查找第二个 //ps3 = strchr(ps3 + 1, 'l'); //复制指定位置后的字符串 char* t = (char*)malloc(strlen(ps3) + 1); strcpy(t, ps3); printf("t = %s ", t); //输出lloworld free(t); printf("*ps3 = %c ", *ps3); //复制指定字符前的字符串 char s4[] = "hello"; char* p1 = strchr(s4, 'l'); char temp = *p1; *p1 = '