C语言总结:
1.常量 :程序运行期间值不能发生改变的量
2.变量 :代表一个存储区域存储区域内存储的内容就是变量的值,变量的值可以在程序运行期间发生改变。
3.变量的定义:类型修饰符 变量名=初始值; 例: int age =23; 注意:在使用变量之前必须对变量进行定义。
变量的命名规则:
①.只能由数字,字母,下划线组成,并且数字不能开头。 ②.不可以与系统保留字同名。
③.不能使用重复的变量名。
④.见名知意(规范)
4.赋值运算符:用于给变量赋值,将右边的值赋值给左边的变量。例:age=24;
赋值运算符优先级的高低
5.算术运算符
对于算数运算符,如有如下分类:
①.单目运算:比如++(递增运算符), - -(递减运算符) ②.双目运算:+、-、*、/、%、(加减乘除以及取余)
③.条件运算符:条件运算符
++/—(递增递减)运算符在前,先执行。运算符在后,后执行。
6.复合运算符
+= -= *= /= %=
7.条件运算符
语法:
条件表达式?真结果表达式:假结果表达式
条件运算符的使用意思就是:询问a大于b是否成立,如果成立则选择冒号左边的变量作为结果,如果不成立,则选择冒号右边的变量作为结果. c=a>b?a:b;
8.表达式
表达式:常量,变量与运算符的组合。
例如:
3+5,a+b,a>b?a:b;
注:表达式都会返回值。
9.基本输入输出函数
格式化输出函数printf
语法形式:
printf(格式串,表达式1,表达式2......);
注意:
最少占4位:
printf(“d”,12);输出:0012 以0补齐
printf("M",12); 保证有效位数至少为4位,不足四位,以空格补齐,
多于四位 约束无效
printf(“%8.2f”,3.1245);输出 3.12
printf(”%-4d”,12);输出 :12 左对齐的概念是有效数据不足指定的位数时,末尾以空格补齐,左对齐时不能使用0来补齐不足位数,因为0会导致原有数据发生改变
转义序列
\n 回车符
\\ 打印\
%% 打印%
格式化输入函数scanf
语法
注意事项:
以回车 确定输入结束。切记 :只有大回车才会结束输入; scanf(”%d%d”,&num1,&num2); 限制输入格式
不要在格式串后面加’\n’字符,否则会抵消人工输入的回车。
++,自增1。 --,自减1;
++, --,在变量的前面,先参与运算,再++,--
++, --,在变量的后面,先++, --,后参与运算
复合运算符, +=, -=, *=, /=, %=,
复合运算符之间不能加空格。
取余运算符的两端都必须为整数。
基本的输出函数
%d 整型 %f 浮点数 %c 字符型 %ld 长整形
com+ shift + z 返回撤销
com + z 撤销
%。2f 代表小数点之后保留两位。
枚举类型是一个构造类型,它使一组整型常量,罗列处理所有的可能性。
定义枚举 使用关键字 enum + 枚举类型的名字 { 枚举值,多个枚举值之间通过使用逗号分隔}; 最后的分号必不可少。
枚举类型将人能够识别的标识符,和计算机能识别的数字对应起来。 if(条件表达式){语句} 当条件表达式的条件成立时,执行大括号内的语句,否则执行if之后的语句。
if(条件表达式) {语句1} else { 语 句2}
break; 结束当前分支,跳出switch,执行之后的语句。
default: default 语句的执行顺序和位置有关,只要为匹配到对应的分支,就会执行
for
<#initialization#> 变量初始化
<#condition#>循环条件
<#increment#> 变量增量
<#statements#>循环体,每次反复执行的内容。
循环变量的名字 先以i,j,k,为主。
while和do while 的区别
对于while 循环,需要先判断循环条件,然后执行循环体,而对于do while 不管条件是否成立,先执行一次循环体,后判断条件。 while 和 for 的区别
while 循环多用于不明确循环次数是使用,而for循环多用于知道循环次数时使用,for循环可以转为while 循环,但是while 循环不可以转为for循环
何时使用循环
当我们做同一件事两次或者两次以上时,就要考虑使用循环,把重复做的操作作为循环体。
break; 跳出当前循环,跳出本层循环,执行之后的语句
continue; 结束本次循环,也就是对于该次循环执行到此结束,然后执行i++,继续下一次循环
随机数,arc4random() 随机函数;
求[a,b]范围内的随机数,arc4random() % (b - a+1)+ a; 定义一维整形数组
1,数据类型 2,数组名 3, 中括号中填写元素个数 4,初值 ,赋值时使用大括号,内部为每个变量赋初值,中间应聘哪个逗号分割。 定义数组时,数组元素的个数只能是常量或者是常量表达式,不能为变量.
取数组中的元素的时候 , 数组名 + 下标.
数组中元素的下标范围 , 0 到数组元素下标 - 1; 数组所占内存空间的大小 = 数组中每个元素所占空间的大小 * 数组元素个数. 外层循环决定比较的趟数
内层循环比较每趟比较的次数.
最外层可以不减一,减一的目的是提高程序效率.
内层必须要减一,目的是为了防止超出数组的范围.
内层 - i 可以不减,作用是缩小无序区的范围,提高程序的执行效率.
字符数组和整形数组一样都是一维数组,只不过数据类型是char. sizeof 用来计算数据类型,变量以及数组所占空间的大小.
strlen() 字符串长度 ,肉眼看到的字符的个数.
strcpy() 字符串拷贝 ,
strcat() 字符串拼接
strcat(str , "ios");
strcmp() 字符串比较
二维数组的定义和一维数组的定义十分相似,只不过和一维数组多了一维,
定义数组 : 数组类型 数组名 [行数][列数] = 初值 (多个元素赋初值要加大括号)
二维数组定义时 第一位可以不给,行数可以省略,但是第二维下标必须要指定
并且第一维下标与第二维下标都必须是常量或者是常量表达式.
字符串数组 , 只不过字符串是存储在一维的字符数组中,所以本质上是一个二维的字符数组.
数组名代表数组的首地址,是一个常量地址,不可被修改.
对字符串进行赋值操作时,要使用strcpy函数.
strcpy(str, name[j]); 将name[j] 字符串中得内容拷贝到临时字符数组str中.
函数存在的意义:把main 函数中复杂的逻辑进行拆分,有一个一个单独的函数来处理一个单独的模块,main 函数只起到宏观调控的作用.
/*
函数的定义 : 包括以下四部分:
1.返回值类型(要返回的数据的类型)
2.函数的名字(给函数起一个名字).
3.参数列表(用来接收传入的数据).
4.函数体(函数真正的功能,实际做的操作).
*/
/*
函数格式:1.无参数 无返回值. void
函数名命名规范: 有单词组成 ,查了第一个单词外,其他单词的首字母 大写.
工程名命名规范: 有单词组成 ,每个单词的首字母都要大写 (是单词,不是拼音)
变量名的命名规范 : 有单词组成,除了第一个单词外,其余单词的首字母都要大写.
*/
/return 用于返回值,将返回的数据放在return之后即可.
谁调用该函数,就将该值返回给谁.
切记,不要把代码放到return 后面.否则会执行不到
4.有返回值,有参数.
求两个整数的最大值;
多个参数之间用逗号间隔
函数与函数之间可以嵌套调用,但是不可以嵌套定义.
Function defintion is not allowed here
在这不允许定义函数.
函数与函数之间存在嵌套定义,(也就是在一个函数体中又定义了另外一个函数)
解决: 就把内部的定义提到函数的外部,让函数与函数之间形成并列关系.
Control reaches end of non-void function
没有到达一个返回值不为空的函数结尾
原因: 非空函数需要返回值,识别到return 之后 意味着函数的结束. 解决方法: 返回最终的数据即可. (return操作)
实参:实际参数,真实的具体数据,也就是在函数调用时给定的参数. 形参:形式参数,只用来表示接受什么类型的数据,具体的存储的数据未知,也就是在函数定义时给定的参数.
函数调用时,实参到形参的传递是一个拷贝的过程.
implicit declaration of function 'maxfive' is invalid in C99. 函数未声明
函数声明和函数定义只是少了函数体,最后加分号.
函数使用三部分 :
1,函数的声明.
2, 函数定义.
3, 函数调用.
函数调用 函数名+ 参数列表(实参)
数组作为参数时,函数调用传入数组名即可
#import "Function.h"
int var = 10; 全局变量,在所有函数中都可以访问.程序运行期间空间不回收.
变量 x y 是在函数内部定义的变量,只能在函数内部有效,在函数之外,就无法访问,所以叫做局部变量,(当函数调用时,为变量开辟空间,当函数结束之后,回收空间.)
int maxValue (int x ,int y)
被static 修饰的变量成为静态变量,
特点: 1.空间值开辟一次,而且在程序运行期间空间不回收.
2. 变量只初始化一次.
3.如果不赋初值.默认为0.
static int sum = 0;
一个函数用来实现一个单独的功能,在函数内部只写与函数功能有关的代码.
函数的使用:
1,函数的声明 ; 写在 .h 文件中
2,函数的定义 ; (函数的实现) ,写在.m 文件中.
3,函数的调用 . (在main.m 文件中的main函数中实现调用)
/a [] 用来接受数组 count 用来接受数组元素个数
void outPutArr(int a[] , int count );
#import "Struct.h"
导入自定义的头文件时,用 " " 导入系统定义的头文件时 使用 < >
数组作为函数参数在传递时,值填写数组名即可.
printAllStudentInfo( b ,5);
/**
* 结构体嵌套,在一个结构体的结构体成员变量是另外一个结构体类型的变量.
*/
int a = 010 + 10 ; 0开头是八进制.
0b 开头是二进制
0x 开头是十六进制
printf("%d " ,a ); %d 打印十进制整数.
%x 打印十六进制. (字母小写) %X 打印十六进制 (字母大写) %o 打印八进制
一个字节 又是八位二进制数.
位运算符
按位与 & (同为1 , 则为1 , 否则 为0 );
按位或 | (同为 0 , 则为 0 , 否则 为 1 );
按位非 ~
按位异或 ^ (相同为 0 ,不同为 1);
左移 运算符 左移一位相对于乘 2 ;
右移 运算符 右移一位相对于除 2 ;
二进制的高四位 和第四位互换.
unsigned char a = 130 ;
unsigned char left = 0; 存储左移之后的结果
unsigned char right = 0 ; 存储右移之后的结果
left = a << 4 ;
right = a >> 4 ;
printf("%d" , left | right) ;
二进制数的奇偶位互换 .
1,偶~奇 (右移一位)
保留奇数位,将偶数位清零 . & 01010101
2,奇 ~ 偶 (左移一位) ;
保留偶数位 , 将奇数位 清零 & 1010101
unsigned char b = 0b10110111;
unsigned char left = 0 ; 存储左移后的结果 unsigned char right = 0 ; 存储右移后的结果
如果想做清零操作使用 按位与 , 清零位为 0 ,保留位为1
(1) 先左移一位
left = b << 1;
(2) 保存偶数位 ,将奇数位清零
left = left & 0b10101010;
(3)右移一位
right = b >> 1 ;
(4)保留偶数位 , 将奇数位 清零
right = right & 0b01010101 ;
(5) 按位或
printf("%d\n" , left | right);
栈区内存分配原则:从高到低分配,从低到高 存取 地址 : 内存单元的编号.
int a = 10 ;
int b = 5 ;
printf("%p %p\n",&a ,&b);
int a [5] = {1,2,3,4,5};
printf("%p \n%p \n%p \n%p \n%p \n %p &a[1] ,&a[2] ,&a[3] ,&a[4] ,a);
printf("%d \n " , 3 ^ 5);
\n" ,&a[0],
定义一个指针变量 , 和定义整型变量类似,也包括三部分:数据类型 变量名 = 初值
只不过指针变量用来存储地址而已.
int * 指针变量类型 , p 指针变量名 , NULL 指针变量初值. int 的作用 : 1,当自增时增加几个字节,2,当存取数据时一次性读取几个字节.
定义时 , * 告诉编译器,后面的变量是一个指针变量;
int * p = NULL ;
指向关系
p = &a; 将a 的地址赋值给p .
printf("%d\n", a); 直接访问 内存单元数据
* p 此时的作用是根据指针变量存储的地址,找到对应的内存单元,将内存单元上的数据读取出来.
printf("%d\n", *p); 间接访问 /间接访问内存单元数据
* p =20 ;
printf("%d\n", a);
printf("%d\n", *p);
对于指针变量类型,所规定的存储空间的大小只和操作系统有关,32位是4个字节,64位是8个字节.
int * p1 = NULL;
赋初值为NULL , 让指针变量指向一个无效的空间.
当对p1 指向的空间进行操作时,p1 必须指向一个有效的空间. p1 = & b;
*p1 = 50 ;
printf("%d\n" , *p1);
int c = 30 ;
p1 = & c ;
指针变量的重新赋值,我们叫做指针重指向 ,只看最后一次指向. printf("%d\n" , *p1);
Incompatible pointer types assigning to 'int * '
incompatible 类型不匹配....
Thread 1 : EXC_BAD_ACCESS (code = 1 , address = 0x0) 没有指向一个有效的空间. 奔溃 crash
指针与数组
int a [ 5] = {10,11,12,13,14};
int * p = NULL;
让p指向数组的首地址 (数组名 a 就代表数组的首地址 , 代表数组中第一个元素的地址).
p = a;
printf("%d \n" , *p);
p ++ ;
for (int i = 0 ; i < 5 ; i ++) {
printf("%d " , *(p + i)); printf("%d " , *(a + i));
}
printf("\n");
当把数组的首地址赋给指针变量p之后,指针变量就可以当做数组名来使用.
数组名是一个常量不可对其更改.
指针数组.(数组中的内一个元素都是一个指针变量).
char str [] = "Frank";
字符数组str 需要存储字符,所以把常量区中Frank 字符串的内容拷贝到数组中. 通过数组操作操作的是栈区的内容.
而对 数组a 来说,数组中的每一个元素都是一个字符型的指针变量,指针变量用来存储地址,所以将常量区中Frank , Duck ,iPhone 的
开始地址拷贝到对应的变量中通过指针操作操作的是常量区的内容. char * a [3] = {"Frank","Duck","iPhone"};
常量区的内容不可更改.
#import 与 #include 相比能够防止重复导入,保证内容值只复制一个.
#include "A.h"
#include "A.h"
多个include 修改如下:
#ifndef lessonPointHigher_A_h
#define lessonPointHigher_A_h
int max(int x ,int y)
{
return x > y ? x :y;
}
#endif
宏 ,只做替换 #开头 指令
命名规则: 1. 全大写 2. k + 驼峰(多个单词组成,每个单词的首字母大写.)
例如 MAX 或者 kMax
宏 不是变量
#define 用来定义宏 COUNT 宏名
无参宏
#define COUNT 10 后面不要加分号
在预编译阶段 COUNT 全部换成 10
使用宏 应注意的问题:
1.定义宏时,最后不能加分号.分号也会成替换内容的一部分
2.参数要加括号
3.对于有参数宏,宏名与括号之间不能加空格
有参宏
#define SUM(A,B) ((A) + (B))
如果先算宏内的运算 定义宏时,加括号 #define SUM(A,B) ((A) +
(B))
宏不限制数据类型
宏 只是替换功能
SUM(5,10) * SUM(5, 10) 等于 65
#define AAAA
int main(int argc, const char * argv[])
{
条件编译 根据条件来编译不同的代码 ,编译期会将源文件编译成二进制指令,存放在代码区.条件编译经常用来调试程序. 条件编译 第一种形式
#ifdef 标识符 代码段1 #else 代码段2 #endif
如果标识符通过#define 定义过,则编译代码段1 , 否则编译代码段2 . #endif 是编译的结束标志.
#ifdef AAAA
int a =10 ;
#else
int a= 20;
#endif
printf("a = %d\n", a);
条件编译 第二种形式
#ifndef 标识符 代码段1 #else 代码段2 #endif
如果标识符没有通过#define 定义过,则编译代码段1 , 否则编译代码段2 . #endif 是编译的结束标志.
#ifndef AAAA
int b =10 ;
#else
int b= 20;
#endif
printf("b = %d\n", b);
条件编译 第二种形式
#if 常量表达式 代码段1 #else 代码段2 #endif
如果 常量表达式 结果非 0 编译器编译代码段1 否则编译代码段2
#if 1
int c = 10;
#else
int c= 20 ;
#endif
结构体指针访问结构体成员,通过指向操作符, 例如:结构体指针变量->结构体成员;
printf("%s \n" ,pStu->name);
strcpy(pStu->name, "xiaoguang");
printf("%s \n" ,pStu->name);
pStu ++ ; 增加的是整个结构体的大小.
*pStu 和 xiaoguang 的功能是一样的.都是获取到结构体的内容.