C语言 指针【指针 || 数组 || 字符串】

地址
在C语言中定义的每一个变量都拥有属于自己的存储单元的地址,
通常我们认为一个变量拥有两个值,一个左值(地址)一个右值(变量的值)
在scanf()中使用到的 取地址符(&),就是向这个地址中输入数据从而给变量赋值
访问地址 就需要用到指针,用于保存地址

对于对象的访问

1.直接访问:通过对象名去实现访问,但有作用域的限制
2.间接访问:通过地址去访问,不受作用域影响

指针
用于保存其他对象的地址值。
在32位的系统中占4个字节,64位的占8个字节

1)指针的定义
	指针变量的定义和其他变量的相同也是: 变量的类型 变量名= 初始值
				int * p = NULL;     指针
		这里表示定义了一个int  * 类型指针p;他初始化直向空(空指针),
		还有一种定义: int * p ;  这种定义,没有赋初始值,他是一个(野指针)指向未知,不知道是否能访问,能否修改。通常我们都是先定义空指针。在给他赋值。
		
2)与指针相关的运算:&取地址符  *指向运算符
		在1中定义p 需要赋值(或者申请空间malloc),才能实现他的作用
		赋值   int  a = 5;
				 p = &a;   //此时将a的地址付给了p,也可以说是p指向了a。
				 此时 *p == 5;
		两个符号可以约掉  *&p == p     但是&*不能
		
3)指针变量作为函数的参数
		形参 = 实参的值,
		指针传入的是地址值,形参和实参指向的是同一个地址,改变形参的值同时会时实参的值发生变化。
		在实现交换两个数的值时,传入地址,改变地址对应的值,可以实现交换,,但是注意的是,有题目是交换了传入的地址,也就是两个形参的地址做了交换,这样并不能交换实参的值。

4)数组与指针
		数组元素是和普通元素是一样的,数组元素也有它自己的地址。
		数组元素也有左值和右值,只不过数组的每一个元素的地址是相邻。
		数组名 可以代表首元素的地址。
		int a[10];	
		a => &a[0],数组名a当作指针来看。
		指针加减,看当前的指向,如一维数组的p=>a =》a[0]    p+1 =>a[1];
		
5)指针常量和常量指针
	指针常量: 指针本身不能改变的,但是指向的空间里面
		的内容可变。
		如: 数组名		int * const a;	
	常量指针:是指向常量的指针。
		指向的对象是常量,那么这个对象不能够改变的。
		指针本身可以被改变,但是指向的空间的内容不能改变。
		const int * a;
		int const * a;
		
6)数组名和指针
	数组名是一个指针常量。
	数组名可以代表整个数组,但有些情况下是当作指针来看的。
	如数组 :   int a[10];
	a <=> &a[0];
	a代表的是a[0]的地址 a+1代表的是a[1]的地址。
	此处的+1移动的是多长需要看当前a代表的是什么来决定。
	如 : int  a[3][4];
	此时 a  代表的就是&a[0]   a+1 =&a[1]   看成3行4列,可以理解为。首先指向的是第0行,加1 ,指向的是第1行,其地址在数值上等于他们那一行的第一个元素的地址。
	如:一维数组
		int a[5] = {1,2,3,4,5};		
		int * ptr = (int *)(&a + 1);    //此时ptr指向了a数组后面的空间
		printf("%d  %d\n", *(a + 1), *(ptr - 1)); // 2  5
	如:二维数组
		*(a[1] + 2)       此时 a[1] 应该当作指针来看
		*(&a[1][0] + 2)
		=> *(&a[1][2])
		=> a[1][2]		//!!!!表示第1行第2列的那个元素   (不要写代表值)
	练习题:
		**a[3][4] 写出表达式的含义 **
			&a[1][0]: 第1行第0列的元素的地址
			a[2]: (1)代表a[2]这一个数组 (2)代表第2行第0列元素的地址
			&a[0] + 1: =》 &a[1]  (1)第一行的地址	
			*(&a[1][0] + 1):  代表第1行第1列的那个元素
			
7)指针数组 与 数组指针
	a)指针数组:
		指针数组是一个数组,不过数组中存放的全是指针
		定义如:int(任意类型都可以)  * p[10];   相当于一个数组里面存放了10个int * 类型的数据		
	b)数组指针:
		数组指针是一个指针,用于指向一个数组
		定义: int (*p)[10];  指向一个有10个元素的数组  <=>  int  a[10];
			
8) 字符串与指针
	字符串就是又一串字符组成 (String类型????C语言中好像还没涉及到这个类型)
		字符串的表达方式有两种
		 a)字符数组
		 	char a [6] = {'a','a','a','a','a','\0'};
		 b)字符指针 
		 	char * p = "abcd"	
	字符串末尾会默认为"\0" 表示字符串结束
	字符串我们只需要保存他的首地址即可,读取时会一直读到0结束
	在C语言里面字符串是保存在一个叫做 .rodata(只读数据)的内存区域。
	只读区域无法修改
		char * p = "123456";
		此时执行 *(p+1)=‘a’; 会出现段错误,因为此区域的数据是无法修改的。
	字符数组
	char a [6] = {'a','a','a','a','a','\0'};
	//与普通的数组相同,保存在一个.data/栈空间,数组区域数据是可读可写的
	同时大小也是与数组相同
	sizeof(a)=6;
	注意!!!使用sizeof时
	char s[] = {'a','b','c','d','e'};// 这种末尾没有0
		sizeof(s) = 5 		
	char s[] = {"abcde"};    //这种末尾会添加0
		=> char s[] = {'a','b','c','d','e','\0'}; 
		sizeof(s) = 6
	《strlen 计算的值不包括0》
			
9) 字符串常用函数
	(1) strlen: 用来求一个字符串的长度 
		头文件:	#include <string.h>
		计算字符串的长度,不包含'\0'
		l = strlen("abcd\nabc"); == 8  // \n看成一个?? \大多数都是表示转义
		l = strlen("123\0123abc\0abc");  == 8   //读到0结束,但是第一个\0并不是末尾,
		我们碰到这样的需要判断他是否为8进制的树,此时\012是当成8进制来看的。
		\XXX 可接一个、两个或三个八进制的数
	(2)strcpy/strncpy   字符串拷贝
		头文件: #include <string.h>
		strcpy(char *dest, const char *src);
		复制  一个字符串到另一个字符串,都是从头开始
		strcpy(没有考虑越界)strncpy增加了长度限制,
			(1) 遇到\0拷贝结束,此时\0也会被拷贝
			(2) 已经拷贝n个字符了(后面的\0不会自动拷贝,除非第n字符为\0)
	(3)strcmp/strncmp
		字符串比较,同样strcmpy是全部比较,strncmp是限制比较的长度
		字符串比较是一个一个字符比较,
		如果 c1>c2 返回 1,如果c1<c2 返回-1
		如果相同则继续比较到下一个字符,知道结束,返回0
	(4)strcat / strncat
		源字符串空间应该足够大。将字符串链接到尾部。
		同样 拷贝到\0结束,strncpy限制大小
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值