TMDBug

Code Change The World And Make It Better!

TMD.Bug

C语言学习笔记(三)

9.位运算

9.1 位运算的或、且、非

位运算:针对一个变量的某一位的操作,称之为位操作;

int a;4字节;32位; 如:int a =5;0000 0000 0000 0000 0000 0000 0000 0101 最低位是第0为;最高位是第31位; 如果想把 第3为的0改成1,那么这就是位运算; 位运算符: & 按位与 | 按位或 ^ 按位异或 ~ 按位取反 << 左移 >> 右移 与运算:每一位进行与,一假即假 * 5&3; * 0000 0000 0000 0000 0000 0000 0000 0101 5; * 0000 0000 0000 0000 0000 0000 0000 0011 3; * 结果为: * 0000 0000 0000 0000 0000 0000 0000 0001 1; * 5&3 == 1; 与的时候,用的是补码; * -1的补码是全1; * 5&-1=5; 判断数字的奇偶; 数字&1 = 1;表示为奇数; 数字&1 = 0;表示为偶数; 或运算:每一位进行或运算;一真即真; 5|3 == 7; 异或运算:a^b;相同为假,不同为真; * 相同为0,不同为1; 5^3 == 6; 按位取反:0为1,1为0;一个数的取反等于他的相反数减一(或者 加 1 取反); 练习 交换两个数的大小 int temp = a;a = b; b = temp; a = a^b;b = a^b;a = a^b; 左移 :每一位都向左移动一位,超出的舍去,末位补零;左移一位相当于乘以2;左移动2位,相当于乘以4;左移动n位相当于乘以2的n次方; 右移:不同的系统右移动的结果不同;移除的部分舍去,正数首位补0;负数补1; 5>>1 == 2 正数右移动一位相当于除以2; 右移动n位,相当于除以2的n次方; -1右移几位都是-1; 【查看a的某一位】如果想求a的第n位(0位起)是1还是0?那么a&(1<<n)==1,则说明第n位是1,如果a&(1<<n)==0,这说明第n位是0; 【将a的某位置成1】a = a|(1<<n);或者a|=1<<n; 【将a的某位置成0】a& = ~(1<<n); 【将a的某位取反】a^=1<<n;

10.结构体、联合体、枚举

结构体:不同类型变量的集合; (数组:相同类型变量的结合)

struct user{
char username[20];
char password[20];
long long userID;
//结构体成员
};

struct user user1;//相当于int a;
结构体指针:指向结构体变量的指针;
结构体可以存储向学生信息这样复杂的内容;

联合体:了解知识,现在实用性不大;
//联合在内存中所占字节数为 它里面属性中最长的变量的字节数 //所有的变量都占同一块内存

union Student
{
int a;
char c;
char name[100];
};

11.动态内存分配

malloc():帮助我们开辟内存空间;
传进要开多少字节的空间;
开的空间会存在堆段;(main函数在栈空间;)
其返回值为void,表示泛型指针;泛型指针可以返回给任何类型的指针变量;
size_t:usigd long;无符号长整型;
堆空间使用完毕,需要释放;用free()函数;如果不释放,程序没有结束的话,堆空间里的函数始终不会消失;必须要释放;
free();释放函数;
exit()函数是终止程序进程;
perror(“报错”)//报错
栈空间:静态内存分配;//编译时决定的;
堆空间:动态内存分配;//运行时决定的;
动态内存:大小 运行时决定;程序员分配的;堆段;手动释放;
静态内存:大小 编译时决定;编译器分配的;栈段;只读数据段;自动释放

#include
#include //动态申请内存导入 stdlib.h 头文件
int main()
{
int a=10;
//静态内存分配
/*
程序执行前就分配好内存
优点:效率高
缺点:缺少灵活性
要求程序执行前就知道所占内存大小
*/

//动态内存分配
/*
我们需要通过指针来间接访问内存
优点:灵活性高
缺点:效率低
*/
// malloc
// malloc : void *malloc(unsigned int size);
int * b = (int *)malloc(sizeof(int));//使用malloc申请的内存 存放在堆区 堆区是没有地址的 只能通过指针找到这块内存
*b = 12;
printf(“%p\n”,b);
// *(b+1)=13; 不合理 不要非法访问别人的内存
// printf(“%d\n”,*(b+100));
int * c= (int *)malloc(sizeof(int)*10);//申请了一块(多个)内存空间 相当于数组
*c=12;
*(c+1)=13; //合理的
//printf(“%d\n”,*(c+1));

//内存使用原则“好借好还”
//释放内存的函数free()
free(b);
free(c);
printf(“%d\n”,*b);
//静态内存是由系统来管理的,自动分配和释放
//动态内存需要程序员分配和释放的 申请的内存忘记释放 叫做内存泄漏
/*
内存管理经常遇到的几个问题:
1.内存泄漏 (申请了内存 使用结束以后 没有释放 一直处于占有状态 其他应用不能使用这块内存)
2.内存提前释放 (我申请的内存还没使用完就被释放了 会造成不可预期的结果)
3.重复释放同一块内存
*/
b = NULL;
c= NULL; //预防野指针
printf(“%p %p\n”,b,c);//指针指向的内存释放 指针变量里面存放的(值)地址不一定不存在 这种现象出现的指针被称为野指针
//野指针出现的原因
/*
1.没有初始化或赋值的指针变量
2.指向已释放的内存空间 没有被赋值为NULL 指向垃圾内存的指针
*/
return 0;
}

12.宏定义、预处理

12.1 宏定义

#include //<>表示导入的头文件是系统文件(库文件)
//编译器直接去库函数里查找 找到就引入 找不到就报错
//#include “” 导入我们自定义的文件
//编译器查找文件路径:现在本程序的目录下查找 找不到就去库函数中查找 再找不到就报错(面试中经常问到)
//定义宏
/*
#define 宏名
注意:无参宏
(1)宏名一般字母要大写 为了和变量进行区分 也不是必须要大写
(2) 宏名前后要有空格
(3)宏定义不是一条语句 所以没有分号
(4)宏定义只是起到替换作用 所以编译系统不会给宏名分配内存空间
(5) 宏名前面没有数据类型 他只起到替换的作用
*/
#define PI 3.1415926
//宏名替代后面的一串符号
#define PI 10
//宏名重复定义,就取后面的值
#define SUM(x,y) ((x)*(y))//(1+2*2+1)为了避免
//带参宏
//(1)参数要用括号括起来 每个参数之间用括号隔开
//(2)每一个参数 要用括号括起来
//(3)一串符号 如果是表达式 要将整个表达式用括号括起来

12.2 预处理

程序执行四个步骤:预处理;编译;汇编;链接; 宏:(如:#define N 6)发生在预处理阶段的单纯的字符串的替换; 解决反复使用到的常量;用宏定义 方便修改; 在宏中没有变量常量、语法,只是单纯的替换; 宏的传参,是单纯的替换;一定要把后边定义的变量都加上括号(); 12.3 typedef 给变量起别名 typedef :给变量类型起别名; (如 typedef int i_t;[i_t就是int的一个别名]) 一般,自创的类型用_t结尾; 怎样声明一个变量,就怎样声明一个别名; size_t:表示大小的正数; typedef:有作用域; #define :宏没有作用域;

13.文件操作

13.1 文件操作相关说明

读:文件—>内存 写:内存—>文件 打开文件:fopen(); FILE * fp = fopen(“./file”,”r”); //“r”:只读, if(!fp){ perror(“fopen”); exit(-1); } fclose(fp); //打开了,就要几个关闭; //void *p;/p是任意指针变量; fread: FILE * fp=fopen(”./file”,”w”)//如果不存在这个文件,会新建一个文件,如果有file这个文件,会清空里边的内容; 清空之后,我们就可以重写; fwrite(文件空间地址[hello,world],单位信息的字节数[1],一共写入多少字节,写到哪个文件[fp]);写入文件的函数; 再次运行fwrite();会接着写入进去,并不会覆盖掉; fclose(fp); FILE * fp=fopen(”./file”,”a”)//a表示apaad,表示写入的时候不会清空里边数据; #include “r+”就是在r的基础上加上写的权限; “w+”就是在写的基础上加上读的权限; “a+”就是在写的基础上加上读的权限; 12.3 举例

#include
#include
#define PATH “/Users/qianfeng/Desktop/file.txt”
int main()
{
/*
strlen();//获取字符串中有效字符的个数 包括空格 遇到\0结束

strcpy(a,b);//字符串间的拷贝 把b拷贝到a里面

strcmp(a,b);//字符串的比较 比较的是相同位置 字符的ASCII值
(第一个字符串大于大二个 返回一个大于0的数 相等返回0 小于返回一个负数)

strstr()查找字符串第一次在父字符串出现的位置

strcat()字符串的拼接 将第二个字符串拼接到第一个的后面 去掉第一个字符串的\0 最后在拼接好的字符串后面添加\0作为结束标识

memset()字符替换
*/
// char * ch=”hello”;
char chArr[]=”helloworld”;
memset(chArr+2,’a’, 5);
//printf(“%s\n”,chArr);

/*
文件操作流程
1.引入头文件
2.定义文件指针
3.打开文件
4.文件读写
5.文件关闭
*/
// FILE * file;
// file = fopen(PATH, “r”);
// //读取一个字符
// char c;
// //scanf(“%c”,&c);
// c=fgetc(file);
// printf(“%c\n”,c);
// //读取字符串
// char chArray[100];
// fgets(chArray, 12, file);
// printf(“%s\n”,chArray);
// fclose(file);

// FILE * file1;
// file1 = fopen(PATH, “w”);
// fputc(‘A’, file1);
// fputs(“hello”, file1);
// fclose(file1);

//文件读写 fread 和 fwrite 的使用
FILE * file2;
file2= fopen(PATH, “r”);
size_t s;
char temp[10];
while (1) {
s= fread(temp, 1, 10, file2);//从第一个字符开始输出10个
if (s==0) {
break;
}
fwrite(temp, 1, s, stdout);//stdout终端输出
}
printf(“\n”);
return 0;
}

<a class="a2a_button_evernote" href="http://www.addtoany.com/add_to/evernote?linkurl=http%3A%2F%2Ftmdbug.com%2Fios%2Fc-language%2F85 click to find out more.html&linkname=C%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%28%E4%B8%89%29″ title=”Evernote” rel=”nofollow” target=”_blank”>
2015年8月13日 0 / /
标签: 

5 + 4 =

回到顶部