C语言-------第四次笔记
指针
指针的定义动态分配内存 结构体 文件读写 头文件与实现文件实例之计算器 文件操作训练之字符串查找
指针的类型
指针的指向内容
指针的运算
数组与指针
指针与函数
指针的定义
- 指针是一个变量
- 指针只能存地址
- 指针占据8个字节空间
int main(){
int *a;
char
printf("a的大小:%d\n", sizeof(a));
printf("a的地址:%p\n",a);
printfC'XdXn", sizeof(b));
}输出:a的大小:8a 的地址:0000000000000001
指针的声明int *p;
char *p;
int *arr[5];
int **p;
- 指针的声明相对于普通变量的声明多了一个一元运算符、”。
- 运算符”是间接寻址或者间接引用运算符。当它作用于指针时,将访问指针 所指向的对象。
- P是一个指针,保存着一个地址,该地址指向内存中的一个变量;下则会访问 这个地址所指向的变量。
- 声明一个指针变量并不会自动分配任何内存。
- 在对指针进行间接访问之前,指针必须进行初始化:或是使他指向现有的内 存,或者给他动态分配内存,否则这个指针会变成野指针。
指针初始化
int a = 5;
int *p = &a;
- " * "定义的时候表明是一个指针变量,使用的时候表示取地址的值
- " & "取某一个变量地
int *p;
p = (int *)malloc(sizeof(int) * 10) free(p);
- 指针的初始化实际上就是给指针一个合法的地址,让程序能够清楚地知道指针的指向,而 不至于变为野指针
指针的类型
- 判断指针类型的方法:去掉星号*和变量名就是指针的类型
- 【C语言-------第四次笔记】P 与 * 结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为 int 型.
- int p[3]
P与[]结合.说明P是一个数组,然后与int结合,说明数组里的元素是整型的.
- int *p[3];
P与[ ]结合因为其优先级比" * "高,所以 P 先是一个数组,然后再与” * ”结合。说明数组里的元素 是指针类型,然后再与int结合,说明指针所指向的内容的类型是整型的.
- int(*p)[3];
P 与 * 结合.说明 P 是一个指针然后再与[ ]结合 (与 ”()” 这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int结合,说明数组里的元素是整型的.
- int **p;
P 与 ** 结合,说是 *P 是一个指针,然后再与 * 结合,说明指针所指向的元素是指针,然后再与 int 结合,说明该指针所指向的元素是整型数据.
- int p(int)
P 与 () 结合.说明 P 是一个函数,然后进入 () 里分析,说明该函数有一个整型变量的参数, 然后再与外面的int结合.说明函数的返回值是一个整型数据.
- int (*p)(int);
P 与指针结合,说明 P 是一个指针,然后与 () 结合,说明指针指向的是一个函数.然后再与 () 里的 int 结合,说明函数有一个int 型的参数,再与最外层的 int结合,说明函数的返 回类型是整型.
指针的指向内容
- 指针存储的内容为变量的地址,也就是说指针的是一个指向作用,指向变量所存储的内容
int main(){
int a = 5;
int *p = &a;
return 0;
}
指针的运算
- 指针+(-)整数
可以对指针变量P进行P++、p--、p + i 等操作,所得錯果也是一个指针,只是指 针所指向的内存地址相比于p所指的内存地址前逬或者后退了 i (对应指针指向类 型对应大小)个操作数。
int main()(char a = *1';
char *p - &a;
printf("p:%p\n",p);
P++;prirrtf("p++之后始果:%p\n",p);
P—;printf("p--之后塔果:Xp\n",p);
叶5;
printf("p+5之后结果:%p\n"/p);
return 0;
}
输出:
p:000000000062FE17
p++之后结果:0e000e0eee62FEi8
p--之后结果:0e0000000e62FE17
P+5之后结果:0000G0000062FE1C
P是一个char类型的指针,指向内存地址0062FE17处。则 p++ 将指向与 p 相邻的下一 个内存地址,由于 int 型数据占4个字节,因此 p++ 所指的内存地址为1000000b。其余类推,不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所 指向的地址.
**********************************************************************************8
数组与指针
- 数组的数组名其实可以看作一个指针,因为数组名是指向数组的第一个元素,上面 num数组指向的也就是第一个元素1,数组名本身是没有占有内存的
int array[10]={0,l,2,3?^,5,6,7,8,9},value;
value-array[0];
value=https://www.it610.com/article/array[3];
value=array[4];
另外一种解释是将数组名指向数组的第0个单元,那么(array+n)也就是一个指向数组 里的第n个单元的指针
P 指向的是数组的首地址,也就是数组的第一个元素,那么 P++ 之后也就是对指针 P 前进了 4(int类型)个操作数,而数组是分配了连续空间,所以相对地址是加减也就是数组元素 的位置变换
指针数组
- 指针数组.是一个数组,数组中的每一个元素都是指针
对于上面的定义和初始化,data是指针数组的名字,也就是指向指针数组首元素的指 针.(指针的指
针).data[i]是data这一个数组的第i个元素,也就是一个指向int的指针 指针可以当成数组来使用。
- 数组指针,是一个指针,它指向一个数组
数组作为参数传入函数的时候,对于被调用的函数参数就是指针
- 函数指针是指向函数的指针变量
- 通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数
- 函数指针可以像一般函数一样,用于调用函数、传递参数,函数指针声明
- 函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的 函数。也就是
说回调函数是由别人的函数执行时调用你实现的函数。
- 为什么需要动态分配内存:
1.存储的数据 需要延长生命周期
2.一个指针变量需要存储数据,变量本身只能存地址
不能存数据,需要分配内存空间来存储数据
#include
#include
int main(){
//char name[100] = {};
//如果使用指针变量接收数据
//必须先为这个指针变量分配一片指向的内存空间
//有内存空间 才能存数据 //导入头文件stdlib.h
//使用malloc (memory alloc)申请内存空间
char *name ;
name = (char *)malloc(10*sizeof(char));
if(name == NULL){
// 申请内存失败
exit(EXIT_FAILURE);
}
scanf("%s", name);
printf("%s\n",name);
//使用realloc动态改变已经分配内存的大小
//增加或者减少
name = (char *)realloc(name, 20*sizeof(char));
if(name == NULL){
//退出之前必须将之前分配的内存释放掉
free(name);
exit(EXIT_FAILURE);
}//使用完毕必须自己手动释放内存
free(name);
return 0;
}
结构体
- 为什么要使用结构体
int , float 只能存单个数据
int num[] 可存储多个数据 但必须同种类型
需要一种类型 可以保存多种数据 - 结构体是什么
int char
一种结构体 - 如何定义结构体类型
注意定义结构体类型时 内部类型不能赋初值
struct student{};
- 结构体内存计算方式
对齐方式 小类型 -》大类型对齐 - 指针使用->访问元素
p->
#include int main(){
struct person {
int age;
float height;
};
return 0 ;
}
文件读写
// 创建文件
#include int main (){
FILE*fp =fopen( "C:\\Users\\33573\\Desktop\\test.txt","a+");
//r:只能读;w:只能写且要覆盖前面的内容;a:可写可读
return 0;
}//打开文件
// 写入内容
fputc fgetc
fputc('a',fp);
fgetc(fp);
// 重新定位文件指针的位置
fseek(fp,3,SEEK_SET);
//SEEK_SET;SEEK_SET;
SEEK_END
fputs("hello world",fp);
// 按照一定格式写入内容
int num[5] = {1,2,3,5,5};
fwrite( num,sizeof(num),1,fp);
//写入的是二进制,视频,音频 结构体
// 读取内容
fdeto(fp);
一行一行读取
int num2[5]= {};
freed(num2,sizeof(num2),1,fp);
for (int i = 0;
i<5;
i++){
printf("%d",num2);
}
//关闭
fclost(fp);
*/
#include
int main (){FILE*fp =fopen( "C:\\Users\\33573\\Desktop\\test.txt","a+");
int num[5] = {1,2,3,5,5};
fwrite( num,sizeof(num),1,fp);
//fputs("hello world",fp);
return 0;
}
头文件与实现文件实例之计算器
主函数 :头文件
- 程序的入口函数
main.cpp 为了让阅读者知道我这里面写的是入口函数- 将不同的功能模块用不同的.h.cpp 来封装
.h 头文件 函数声明 (不能实现)
.cpp .c 实现文件 函数的具体实现{}- 导入头文件进行使用
#include //1.程序的入口函数
//main.cpp 为了让阅读者知道我这里面写的是入口函数//2.将不同的功能模块用不同的.h.cpp 来封装
//.h头文件函数声明 (不能实现)
//.cpp .c实现文件 函数的具体实现{}
// 3. 导入头文件进行使用
#include "calculator.h" int main(){
int a,b;
scanf("%d %d" ,&a,&b);
int result = add(a,b) ;
printf("a + b = %d\n",result);
printf("a + b = %d\n",add(a,b));
printf("a - b = %d\n",minus(a,b));
printf("a * b = %d\n",mulitply(a,b));
printf("a / b = %d\n",devide(a,b));
return 0;
}
实现文件
//1. 先导入需要的头文件
//2.实现这个头文件的 所有方法
#include "calculator.h"
//加法
int add(int a,int b){
return a + b;
}
//减法
int minus(int a,int b){
return a - b;
}
// 乘法
int mulitply(int a,int b) {
return a * b;
}
//除法
int devide (int a,int b){
if (b == 0){
return 0;
}else {
return a/b;
}
return 0;
}
头文件里声明函数
#include //头文件里声明函数
int add(int a,int b);
//加法
int minus(int a,int b);
//加法
int mulitply(int a,int b) ;
//乘法
int devide (int a,int b);
//除法
文件操作训练之字符串查找 头文件
#include
#include "myString.h"/*
* fafjalfjasdfjsadlf
* kfjakfj
* fslf
* ksdfjlafjalsf
*/
int main(int argc, const char * argv[]) {
char sentence[100] = {};
char word[20] = {};
input(sentence, "请输入语句");
input(word, "请输入查找的单词");
int count = find(sentence, word);
printf("出现%d次\n", count);
return 0;
}
实现文件
#include
#include "myString.h"//%s 遇到空格或者\n
//scanf不能输入带空格的字符串
//只能自己定义一个输入语句的方法
void myScanf(char *p){
int i = 0;
while (1) {
char c = getchar();
if (c == '\n') {
p[i] = '\0';
break;
}
p[i] = c;
i++;
}
}void input(char *p, char *des){
//提示用户操作
printf("%s:", des);
//输入语句
myScanf(p);
}//计算字符串的长度
int length(char *p){
int i = 0;
//for (;
p[i] != '\0';
i++);
while (1) {
if (p[i] == '\0') {
break;
}
i++;
}
return i;
}int find(char *sentence, char *word){
//1.获取两个字符串的长度
int sLength = length(sentence);
int wLength = length(word);
//2.判断查询的字符串长度是否比句子短
if (sLength < wLength) {
return 0;
}
/*
hjako jack ,jac;
i = 2
jac
j = 2
*/
int start = 0;
int count = 0;
for (int i = 0;
i < sLength;
i++) {
//记录当前开始的位置
start = i;
//从当前位置开始去和查找的单词进行比较
int j = 0;
for(;
j < wLength;
j++){
//判断j对应的值和start+j比较
if (sentence[start+j] != word[j]) {
break;
}
}//判断怎么出来的
if (j == wLength){
//都相同
//将i的值定位到start+j的位置
i = start + j-1;
count++;
}
}return count;
}
导入函数
#include
#include "myString.h"
void input(char *p,char *des);
int find(char *sentence,char *word);
推荐阅读
- 第6.2章(设置属性)
- 2018-02-06第三天|2018-02-06第三天 不能再了,反思到位就差改变
- 第三节|第三节 快乐和幸福(12)
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- android第三方框架(五)ButterKnife
- 开学第一天(下)
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- 2018年11月19日|2018年11月19日 星期一 亲子日记第144篇
- 第326天
- 跌跌撞撞奔向你|跌跌撞撞奔向你 第四章(你补英语,我补物理)