指针基础二


一、指针强转介绍

指针强转:实现指针变量类型的统一,归一化指针加一的偏移量。

int arr[] = {1, 2, 3};
int* p = arr;
// int == long <= long long
long long *L = (long long*)p;
printf("%lld ", *L); # 每次偏移八个字节
// 指针自增相当于 p = p + sizeof(指针变量类型)*1;
p++;

// 值得注意的是:指针加一与指针自增效果截然不同,加一仅为4字节,自增为指针自身的 Size。
p = p + 1;

二、知识点

1.内存开辟区别

注意点:Wins端为小端存储模式,即对于单个变量(低字节存于低位,高字节存于高位)

  1. 栈内存开辟:从高地址向低地址进行内存开辟。
    PS: 每个变量开辟内存时,会有上下各四字节的边界变量。
  2. 数组内存开辟:从低地址向高地址进行数据存储。
    在这里插入图片描述

2.一级指针与二级指针

二级指针(一级指针地址) --》 一级指针(变量地址) --》变量(数值)

int a = 10;
int* p = &a;
int** pp = &p;

/* 
**pp == a;
*pp == p == &a;
pp == &p;
-----------
p = &a;
*p = a;
*/

3.Const与指针

3.1 Const 与一级指针

主要观察const与指针星号的关系:
const*p 限制域为 *p (指针所指的数值)
*const p 限制域为 p(指针变量)

三种形式:

  1. int* const p;
  2. const int* p;
  3. int const* p;
int a = 0;
int b = 0;
const int* p = &a;// 限制域为 *p
*p = 10;// 触及限制域*p,指向内容不可修改
p = &b; // true

int* const q = &a; // 限制域为 p
*q = 10; // true
q = &b; // 触及限制域p,一级指针地址不可更改

const int*const r = &a; // 限制域为 *p,p
*r = 10; // Error
r = &b; // Error
const int a=0;
const int b=0;
//该语句若无const则语句错误,若正确,则代表可以通过指针改变a的值,所以语句应加上const来确保a的值不会改变
const int *p=&a;

3.2 Const 与二级指针

相比于一级指针,二级指针有更多的组合,即需要注意限制域之间的联系。

int a = 0; int b = 0;
const int *p = &a; // 限制域:*p
int *const q = &a; // 限制域:*p,q
int **s1 = &p;     
   s1 = &q; // 修改二级指针,未触发限制域
   **s1 = 20; // 触发限制域 *p, **s1(*&p) == *p(*&a) == a


const int **t1 = &p; // 限制域:**t1
*t1 = &b; // 修改 *t1,未触发限制域
**t1 = 10; //Error,触发限制域 **t1
int * const* s2 = &p; //二级指针s2指向一级指针p的地址,设置限制域:*s2 == p,即不允许修改二级指针的“内容”
*s2 = &a;  //Error,触发限制域 *s2
**s2 = 100; //True

课堂练习

const int a = 0; // 设置常变量
int b = 0;
const int *p = &a; // 常变量对应的指针应为常指针,限制域:*p
p = &b;  // True
*p = 10;  // Error,触发限制域*p
const int *const *s = &p; // 限制域:**s(*&p),*s(p, *&a)
*s = &a; //Error,触发限制域*s
**s = 10;  //Error,触发限制域**s
const int ** t = &p; // 限制域:**t(*&p)
**t = 10 //Error,触发限制域**s
p = &a; // True
*t = &a; // True

作业练习

作业一
用指针加 const 限制实现 strlen,strcmp(const charstr,const charsrc), strcat, strcpy函数

// 实现 strlen,strcmp(const char*str,const char*src), strcat, strcpy函数
// Strcmp函数
int str_cmp(const char* str1, const char* str2) {

	assert(str1 != NULL && str2 != NULL);

	while (*str1 == *str2)
	{
		if (*str1 == '\0') {
			return 0;
		}
		str1++;
		str2++;
	}

	return *str1 - *str2;

// Strlen函数
int str_len(const char* str1) {

	int count = 0;

	while (*str1 != '\0') {
		count++;
		str1++;
	}

	return count;
}

// Strcpy函数
int str_cpy(char* str, const char* str1, int len) {

	int output = (len > (strlen(str1) + 1));
	int str1_len_temp = str_len(str1);

	if (output > 0) {
		for (int i = 0; i < str1_len_temp; i++) {
			*(str + i) = *(str1 + i);
		}

		output = 1;
	}
	return output;
}

// Strcat函数
int str_cat(const char* str1, const char* str2, char* str, int len) {

	int output = (len > (strlen(str1) + strlen(str2) + 1));

	if (output > 0) {
		str_cpy(str, str1, len);
		str_cpy(str + str_len(str1), str2, len);

		output = 1;
	}

	return output;
}

int main(){
	char str1[] = "Hello";
	char str2[] = "Hey";

	const int strs_len = 20;
	// 切记按照标准,初始化,否则str_cpy时会出现拷贝字符不统一。
	char strs[strs_len] = "0";

	int cpy_temp = str_cpy(str1, strs, strs_len);
	int cat_temp = str_cat(str1, str2, strs, strs_len);

	int output = str_cmp(str1, str2);
	int str_lens = str_len(str1);
	
	return 0;
}

作业二
实现:atoi (必须) itoa函数 (思考)

// 实现:atoi (必须)   itoa函数 (思考)
int my_atoi(char* pstr) {

	assert(pstr != NULL);

	int num = 0;
	bool flag = false; // 标记正负号
	// 跳过空格区
	while (*pstr == ' ') 
	{
		pstr++;
	}
	// 正负号处理
	if (*pstr == '-' || *pstr == '+') {
		if (*pstr == '+') {
			flag = true;
		}
		pstr++;
	}
	// 判断数字,并将字符串转换为数字
	while (*pstr >= '0' && *pstr <= '9')
	{
		num = num * 10 + (*pstr) - '0';
		pstr++;
	}
	// 添加正负号
	num = num * (flag ? 1 : 0);

	return num;
}

总结

今天主要讲了指针的强转, Const与指针之间的关系(注意二级指针的调用关系)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值