AutoLeader控制组——C语言指针笔记

目录

一.指针

一.9.1-1取地址符的用法

二.9.1-2指针变量 

 三.9.1-3指针的用途 

四.9.1-4 指针与数组

五.9.1-5指针与const

六.9.2-1指针的运算

七.9.2-2动态内存分配

二.字符串

一.10.1-1字符串

二.10.1-2字符串变量

三.10.1-3字符串输入输出

四.10.1-4字符串数组

五.字符串函数

一.10.2-1putchar 和 getchar

以下函数需要用到头文件string.h

二.10.2.2 strlen

三.10.2-3strcmp

四.10.2-4strcpy

五.10.2.5 strcat

六.10.2.6 strchr

七.10.2.7 strstr和strcasestr

三.结构体

一.11.1-1枚举

二.11.1-2结构类型

 三.11.1.3结构与函数

1.结构作为函数参数

2.输入结构

3.结构指针作为参数

四.11.3-1类型定义

 

一.指针

一.9.1-1取地址符的用法

#include<stdio.h>
int main ()
{
    int i=0;
    int p;
    //强制转换使p为int型的地址
    p=(int)&i;
    printf("0x%x\n",&p);
    //%p是16位进制打印地址,要输出地址要用%p
    printf("%p\n",&i);
    //p=(int)&i++;错误!&右边必须是变量
    
    
    
    
    int a[10];
    //前三个输出一样的地址,最后一个地址多了4,多了一个int的空间
    printf("%p\n",&a);
    printf("%p\n",a);
    printf("%p\n",&a[0]);
    printf("%p\n",&a[1]);
    return 0;
}

二.9.1-2指针变量 

#include<stdio.h>
void x(int *p)
{
 //*是单目运算符,用来访问该地址的变量,即p的值
    printf("%d\n",*p);
//通过*p来改变p的值    
    *p=27;
}
int main ()
{
    int i=6;
    x(&i);
    printf("%d\n",i);
    return 0;
}

 三.9.1-3指针的用途 

#include<stdio.h>
//用途一:当需要返回多个变量时用指针
void swap(int *p,int *q)
{
	int t=*p;
	*p=*q;
	*q=t;
}
//用途二:当返回值可能出错时用指针
void chu(int x,int y,int *result)
{
	int ret=1;
	if(y==0)
	{
		ret= 0;
	}
	else
	{
	 *result=x/y;
	}
	return ret;
}
int main ()
{
	int a=5,b=6;
	swap(&a,&b);
	printf("a=%d\nb=%d\n",a,b);
	
	
	
	int x=10,y=2,result;
	if(chu(x,y,&result))
	{
	printf("%d",result);
	}
	return 0;
}

四.9.1-4 指针与数组

#include<stdio.h>
//int a[]实际上是指针,指向a[0]
//数组变量本身表达地址(取地址不需要用&),但是数组的单元表达不是(取地址要用&)
void arr(int a[])
{
	printf("arr sizeof(a)=%lu\n",sizeof(a));
}
int main ()
{
	int a[]={1,2,3,4,5,6,7,8,9,10};
	printf("main sizeof(a)=%lu\n",sizeof(a));
	arr(a);
//p是一个指针指向数组时,可当作数组来用
	int *p=&a;
	printf("p[1]=%d",p[1]);
	return 0;
}

五.9.1-5指针与const

#include<stdio.h>
void f(const int*i)
{
//通过const指针来传递地址可以让传递的量保持不变
//并且可以使非const转化为const
}
int main ()
{
	int i=16;
	int j;
//这个指针是const,表示该指针只能指向i的地址不能再指向其他地址
//*p=26是可以的,但是p++不行,因为*p是改变i的值,p++是改变p所指的地址
	int * const p=&i;
//int*是const,表示q可以指向其他地址,但是不能通过*q来改变i的量
//注意,q所指的i可以改变如i=26;
	const int *q=&i;
	q=&j;
//const 在*的左边或右边决定int*是const 还是指针是const
	return 0;
}

六.9.2-1指针的运算

#include<stdio.h>
int main ()
{
//如下所示,指针p+1所加并非1而是它的类型
//如sizeof(char)=1就加1,sizeof(int)=4则加4
//
	char ac[]={0,1,2,3,4,5,6,7,8,9,-1};
	char *p=ac;
	printf("p =%p\n",p);
	printf("p+1 =%p\n",p+1);
//	*(p+n)<->ac[n];
    while(*p!=-1)
    {
//*是运算符,优先级没++高所以*p++的意思是:取p所指的那个数据的值,再让p+1即指向下一位地址
    	*p++;
	}
	
//不同类型的指针是不能直接赋值的,可以强制转换(初学者算了)
	
	int ai[]={0,1,2,3,4,5,6,7,8,9,};
	int  *q=&ai[0];
	printf("q =%p\n",q);
	printf("q+1 =%p\n",q+1);
//*(q+1)是指q指向下一位地址
//注意*q+1无任何意义,因为其作用是使q指向的地址+1而一个int需要+4才能到第二位
	printf("q+1=%d\n",*(q+1));
	int *q1=&ai[5];
//实际上指针相减所得并非地址之差,而是地址之差/sizeof(...)
	printf("q1-q=%d\n",q1-q);
	return 0;
}

七.9.2-2动态内存分配

1.需要包含头文件<stdlib.h>

2.a=malloc(n*sizeof(char) )申请一块有n个char的空间

3.(int*)malloc(n*sizeof(char) )强行使char转换成int

4.使用完后需释放内存free( a )

5.若申请内存没释放则会使程序运行内存下降

6.free过了再free程序会崩溃

7.改变了地址去free,程序也会崩溃

二.字符串

一.10.1-1字符串

1.以整数0结尾的字符串

2.0和‘\0’是一样的,但是和‘0’不同

3.0标志字符串的结束,但它字符串的一部分

4.字符串以数组的方式存在,可用数组或指针的形式访问

5.string.h里有很多处理字符串的函数

6.不能用运算符对字符串进行运算

二.10.1-2字符串变量

·

#include<stdio.h>
int main ()
{
	//指针:这个字符串不知道在哪里
	//需要动态分配空间
	char *str="Hello";
	//数组:这个字符串在这里
	//作为本地变量自动被回收
	char word[]="Hello";
	return 0;
}

三.10.1-3字符串输入输出

#include<stdio.h>
int main ()
{
	char string[8];
	char string2[7];
	//%s是读入一个单词(读到空格、TAB或回车为止)
	//但此方法不安全,因为不知道string的长度
	scanf("%s",string);
	//这是安全的,因为最多只能读七个字符
	scanf("%7s",string2);
	printf("%s",string);
	/*
	常见错误:
	char *string;
	scanf("%s,string);
	以为char*是字符串类型,定义了一个字符串类型的变量string就可以直接使用了
	由于没有对string初始化0,所以不一定每次运行都会出错
	*/
	
	
	
	//这是一个空字符,buffer[0]=='\0'
	char buffer[100]="";
	//这个数组的长度只有1!
	char buffer2[]="";
	return 0;
}

四.10.1-4字符串数组

#include<stdio.h>
int main ()
{
	//二维数组第二个中括号必须有数来表示每位限制的字符数
	char a[][10]=
	{
		"hello",
		"bewoew",
		"dsadsa"
	};
	
	return 0;
}

五.字符串函数

一.10.2-1putchar 和 getchar

#include<stdio.h>
int main ()
{
	//向标准输出写一个字符
	//返回了几个字符,EOF(-1)表示失败
	int putchar(int c);
	//向标准输入读入一个字符
	//返回类型是int 是为了返回EOF(-1)
	int getchar(void);
	int ch;
	while(ch=getchar()!=EOF)
	{
		putchar(ch);
	}
	return 0;
}

以下函数需要用到头文件string.h

二.10.2.2 strlen

作用:用来计算字符串长度

使用方法如下

printf  ( "%lu", strlen ( a ) );

代码如下

size_t mystrlen(const char*s)
{
	int cnt=0;
	while (s[cnt]!='\0')
	{
		cnt++;
	}
	return cnt;
}

三.10.2-3strcmp

作用:用来比较两个字符串的大小

使用方法如下

int strcmp ( const char*s1 , const char*s2 );

若s1<s2 则返回 -1

若s1==s2 则返回0

若s1>s2 则返回1

数组代码如下

int mycmp(const char*s1,const char*s2)
{
	int idx=0;
	while(s1[idx]==s2[idx]&&s1[idx]!='\0')
	{
		idx++;
	}
    return s1[idx]-s2[idx];
}

指针代码如下

int mycmp(const char*s1,const char*s2)
{
	while(*s1==*s2&&*s1!='\0')
	{
     s1++;
     s2++;
	}
    return *s1-*s2;
}

四.10.2-4strcpy

作用:把一个字符串拷贝到另一个字符串上

使用方法如下

注意一下版本不安全,因为不知道字符串是否有足够空间

char *strcpy(char *restric dst , const char*restric src );

把src的字符拷贝到dst上

restric表明src和dst不重叠

数组代码和指针代码如下

char *mycpy(char*dst,const char*src)
{
    //数组代码
	int i=0;
	while(src[i]!='\0')
	{
		dst[i]=src[i];
		i++;
	}
	dst[i]='\0';
	return dst;



    //指针代码
    char *ret=dst;
	while(*dst++=*src++);
	return ret;
}

安全版本如下:

char*strncpy( char*restric dst , const char*restric src , size_t n) ;

n表示最多能拷贝多少字符

五.10.2.5 strcat

作用:把一个字符串连接到另一个字符串上

安全版本如下:

char *strncat(char*restric s1 , const char*restric s2, size_t n);

六.10.2.6 strchr

作用:在字符串中寻找字符

使用方法如下:

char*strchr(const char *s , int c);从左往右找

char*strrchr(const char*s , int c);从右往左找

若返回NULL则表示没找到

寻找字符的代码如下,结果返回llo

	char s[]="hello";
	char*p=strchr(s,'l');
	char*t=(char*)malloc(strlen(p)+1);
	strcpy(t,p);
	printf("%s\n",t);
	free(t);

七.10.2.7 strstr和strcasestr

strstr作用:在一个字符串中寻找一个字符串

使用方法如下:

char*strstr(const char* s1,const char* s2);

strcasestr作用:在一个字符串中寻找一个字符串并且忽略大小写

使用方法如下:

char*strcasestr(const char* s1,const char* s2);

三.结构体

一.11.1-1枚举

定义:枚举是一种用户定义的数据类型

用法:用关键字enum以如下语法来声明

enum 枚举类型名字(可忽略){名字0 ,名字1,名字2,......,名字n};

注意:

在C语言中枚举变量其实是int,可以作为数输出,但实际上很(bu)少(hao)用

如果有意义上排比的名字,用枚举比用const int 方便

二.11.1-2结构类型

使用方法如下

struct  结构名字{ int a1, int a2, .....  } ;

用  运算符访问结构体成员

注意:结构体末尾需要加上分号

若该结构在函数内部声明则只能在该函数内使用

结构变量和数组变量不同,结构变量的名字并不是结构变量的地址,必须使用&运算符

代码如下

#include<stdio.h>
struct date
{
	int year;
	int month;
	int day;
};
/*该代码是声明p1和p2两个结构变量 
struct point{
    int a;
    int b;
} p1,p2;
*/
int main ()
{
    struct date today;
    today.day=24;
    today.month=10;
    today.year=2022;
    printf("Today is %d-%d-%d\n",today.year,today.month,today.day);
	
	//可用如下方式给结构变量赋值
	struct date thisday={.month=10,.year=2022
	};
	struct date otherday={2022,10,24
	};
	return 0;
}

 三.11.1.3结构与函数

1.结构作为函数参数

·整个结构可以作为参数的值传入函数

·这时候是在函数内新建一个结构变量,并复制调用者的结构的值

·也可以返回一个结构

·这与数组完全不同

2.输入结构

·没有直接的方式可以一次scanf一个结构

·记住C在函数调用时是传值的,可用如下方法进行main函数中的赋值

#include<stdio.h>
//声明一个结构体
struct point
{
	int x;
	int y;
};
//声明结构体函数
struct point getStruct(void);
int main ()
{
	struct point y={0,0};
	//让p与结构体函数的值相等
	y=getStruct();
	return 0;
}

struct point getStruct(void)
{
	//在函数中定义一个结构体变量,为了给main中的结构体变量赋值
	struct point p;
	scanf("%d",&p.x);
	scanf("%d",&p.y);
	return p;
}

3.结构指针作为参数

·用->(减号+大于号)表示指针所指的结构变量中的成员  如:p->month=12;

#include<stdio.h>
//声明一个结构体
struct point
{
	int x;
	int y;
};
//声明结构体函数
struct point* getStruct(struct point*);
int main ()
{
	struct point y={0,0};
	getStruct(&y);
	return 0;
}

//用指针的方式给结构体变量赋值
struct point* getStruct(struct point *p)
{
	scanf("%d",&p->x);
	scanf("%d",&p->y);
	return p;
}

四.11.3-1类型定义

C语言中有函数typedef来自定义数据类型 如下:

typedef int length; 左边是原变量,右边是变量的别名.

 作用:使length成为int 的别名(length可代替int出现在变量定义和参数声明中)

	typedef struct Adate{
	int month;
	int year;
	int day;
	//使Date成为struct Adate的别名
	}Date;
	//如下
	Date d={
		12,2022,13
	};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值