16C语言——指针

本文详细探讨了指针的基础概念,包括指针的定义、运算符、与数组的关系,如二级指针、void指针和const特性。还讲解了指针数组与数组指针的区别,以及指针在处理一维和二维数组中的运用。最后总结了指针在编程中的核心地位及其高级技巧。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一、指针的概念

一组概念:

地址:内存用来区分不同字节空间的编号
指针:指针就是变量
指针变量:用来存放指针的变量,称为指针变量

c语言中的两种访问变量的方式:

直接访问:通过变量名访问变量的存储空间:
间接访问:通过变量中存放的地址范文变量空间

二、指针使用

1.定义

存储类型 数据类型 * 变量名;

代码如下(示例):

int *a;
char *b;

2.指针运算符

&:获得变量在内存空间中的首地址
*:作为左值右值
左值:将右值放入指针指向的空间
右值:直接获取指针指向空间中的值

3.初始化

野指针:未经初始化的指针,指向空间已经被回收的指针
空指针;指向内存地址为0x0空间的指针
int 8p = NULL;

4.存储

所有的指针类型都是只有4字节

5.运算符

加(++):向高地址偏移基类型个字节空间
减(—):向低地址偏移基类型个字节空间
两个指针进行减运算:两个数据类型之间间隔多少个数据类型元素

三、指针和数组的关系

1.指针与一位数组的关系

int a[5]  ={1,2,3,4,5};
数组的数组名就是一个常指针,总是指向该数组的首元素,不能做自加运算。
a可以被看成是int*类型
一下两种情况除外:
	1.sizeof()
	2.&运算
	对数组a进行取地址会变成数组指针
访问元素的方式:
a[n] = *(a+n)=*(p+n)=p[n] 
数组的本质就是:只有首元素有变量名,而数组中的其他元素是通过数组下标或者是指针的偏移量来进行访问的

2.指针与一维字符数组的关系

用于遍历字符串中所有的元素
char ch[20] = { hello world};
char * pstr = ch;
while(pstr)
{
*	*(pstr);
	psrt++;
	
}

区别两种定义方式*************************:

char ch[20] - {"hello world"};
//存储:在栈区
//修改:只要数组空间足够可以使用strcpy()修改里面的内容
strcpy(ch,"china");//这样操作是允许的
//指向:数组的首元素是一个常量,所以他的指向不能发生变化
ch = "china";//这样做是错的,常量不可以修改
/*-----------------------------------------------------*/
char *pstr = "hello world";
//存储:在字符串常量区
//修改:不能修改在数据区的常量都是只能读不能改
strcpy(pstr,"china");//这样操作是不允许的
//指向:指针的指向可以发生改变。
pstr= "china";//可以修改指针的指向

四、指针高级

1.二级指针定义

指向指针变量的指针

int num = 0;
int *p = #
int **q = &p;

2.二级指针使用

1.函数体内部修改指针的指向

#include <stdio.h>
int fun(char ** pstr)
{
	*pstr = "hello world";
	return 0;
}
int main(int argc, const char *argv[])
{
	char * pstr = NULL;
	fun(&pstr);
	printf("%s\n",pstr);
	return 0;
}

2.指针数组

3.void类型指针

void *;

  1. 存放地址
  2. 无法执行*操作
  3. void *可以直接赋值给其余指针类型,其余类型指针转换为void时必须类型转换
    例题1:
    给地址为0xbf12cf开始的空间赋值为100;
    *(int *(0xbf12c)) = 100;
    例题2:
    memcpy:内存拷贝

3.const

const修饰的五种情况
1.const char *p;
2.char const *p;
3.char * constp;
4.const char * const p;
5.char const *const p;
1和2等价:
const修饰 * p的值可以改变,但是无法通过指针变量p修改内存空间中的值
3
const修饰 p的值不能改变,可以通过指针变量p修改内存空间中的值,注意要初始化
4和5等价:
指针的指向跟指针指向的内存中的值都不能改变,注意要初始化

五、指针数组与数组指针

1.指针数组:

int *a[5];
定义了一个数组,数组名为a,有5个人元素,每个元素均为int *类型占20个字节空间
字符串指针数组
char * p[5] = ;
每个元素保存一个字符串首地址,可以才做字符串数组

(1)例如对字符串数组进行排序

注意:
(1)存储数据时候,需要开辟空间进行数据存数。
(2)数组的操作则需要用指针数组进行,需要内存空间少每次只有4字节

#include <stdio.h>
#include <string.h>

//从终端接收5个字符串
int get_str(char (* s)[32], int n)
{
	int i =0;
	for(i =0; i< n;++i)
	{
		gets(s[i]);
	}
	return 0;
}
//将收到字符串进行展示
int show_str(char *s[5], int n)
{
	int i =0;
	for(i =0; i< n;++i)
	{
		printf("%s\n",s[i]);
	}
	return 0;
}
//将指针数组的指向该改变,改变指针的指向需要用二级指针
int swap_str(char **p1,char **p2)
{
	char *ptemp = *p1;
	*p1 = *p2;
	*p2 = ptemp; 
	return 0;
}
//对字符串数组进行排序,冒泡
int sort_str(char *s[5],int n)
{
	int i =0;
	int j =0;
	for(i =0 ; i<n;++i)
	{
		for(j = 0 ;j < n - i -1;j++)
		{
			if(strcmp(s[j],s[j+1]) > 0)
			{
				swap_str(&s[j],&s[j+1]);
			}
		}
	}
	return 0;
}
int main(int argc, const char *argv[])
{
	//定义二维数组
	char s[5][32] ={ 0};
	//指针数组指向二维数组
	char *pstr[5] = {s[0],s[1],s[2],s[3],s[4]};
	//获取字符串
	get_str(s,5);
	//排序
	sort_str(pstr,5);
	//输出
	show_str(pstr,5);

	return 0;
}

2.数组指针:

int (*p)[5]
定义了一个指针,指针的变量名为p,占4个字节,指针指向一个5个人整形元素的数组
指向20个字节

  • a :整个数组的首地址,类型为数组指针类型
    数组指针取* ,值不变,类型降级为指向数组第一个元素的指针

六、指针与一维数组的关系

int a[5] = {1,2,3,4,5};
数组的数组名a 是指向数组的第一个元素的指针
a == &a[0];
两种特殊情况,a不能理解为Int*类型
1sizeof
2/&

七、指针与二维数组的关系

1.数组的数组名是指向数组第一行所有元素的数组指针
int a[m][n] = [1,2,3,4,5,6];
访问方式
直接访问
(1)a[m][n]
(2)* (a[m]+n)
(3)* (* (a+m)+n)
间接访问:
p = a[0][0];
p = a[0];
p = *a;

  • (p+M*N+n);
    定义一个数组指针
    int (*q)[3];
    q = a;
    a[1][1] == (a[1]+1)== ( *(a+1)+1);
    在这里插入图片描述
#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a[2][3] = {1,2,3,4,5,6};
	printf("=======================\n");
	printf("&a[0][0]:%p\n",&a[0][0]);
	printf("&a[0][1]:%p\n",&a[0][1]);
	printf("&a[0][2]:%p\n",&a[0][2]);
	printf("&a[1][0]:%p\n",&a[1][0]);
	printf("&a[1][1]:%p\n",&a[1][1]);
	printf("&a[1][2]:%p\n",&a[1][2]);
	printf("=======================\n");
	printf("a[0]:%p\n",a[0]);
	//因为a[0]的类型为int *,所以会偏移4字节
	printf("a[0]+1:%p\n",a[0]+1);
	//不是断错误因为空间为连续,为a[1][0]的地址
	printf("a[0]+3:%p\n",a[0]+3);
	printf("a[1]:%p\n",a[1]);
	printf("a[1]+1:%p\n",a[1]+1); 
	printf("=======================\n");
	printf("*a[0]:%d\n",*a[0]);
	//因为a[0]的类型为int *,所以会偏移4字节
	printf("*(a[0]+1):%d\n",*(a[0]+1));
	//不是断错误因为空间为连续,为a[1][0]的地址
	printf("*(a[0]+3):%d\n",*(a[0]+3));
	printf("*a[1]:%d\n",*a[1]);
	printf("*(a[1]+1):%d\n",*(a[1]+1));
	//验证a为数组指针,偏移12字节单位
	printf("=======================\n");
	printf("a:%p\n",a);
	printf("a+1:%p\n",a+1);
	//对数组指针进行*操作,将数组指针降级为指向该行第一个元素的指针
	printf("=======================\n");
	printf("*a:%p\n",*a);
	printf("*a+1:%p\n",*a+1);
	//访问二维数组中的某个元素
	printf("=======================\n");
	printf("**a:%d\n",**a);
	printf("*(*a+1):%d\n",*(*a+1));
	printf("*((*a+1)+1):%d\n",*(*(a+1)+1));
	 


	
	return 0;
}

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值