Cday02---指针问题(下)

1.指针的步长

在这里插入图片描述

void test()
{
	//指针步长:指针变量+1,要向后跳多少字节
	char* p1 = NULL;
	printf("%d\n", p1);
	printf("%d\n", p1 + 1);
	printf("----------------------------------\n");
	int* p2 = NULL;
	printf("%d\n", p2);
	printf("%d\n", p2 + 1);
	//指针步长由指针类型决定
}

在这里插入图片描述
指针的类型不单单决定指针的步长,还决定解引用时从给定地址开始取类型大小的字节数。

void test()
{
	char buf[1024] = { 0 };
	int a = 100;
	//memcpy表示拷贝内存,变量a为整数型,buf为字符串,所以不能直接使用字符串拷贝strcpy
	memcpy(buf + 1, &a, sizeof(int));//4个字节的数据存放在buf+1的后4位的位置
	
	char* p3 = buf;//将指针指向buf首地址
	/*p3+1表示a的首地址,因为p3为char类型,所以加一个*表示取首地址后一个字节的内容
	再加int*表示取4个字节*/
	printf("*(int *)(p3+1) = %d\n", *(int*)(p3 + 1));
}

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>//可计算偏移量

struct Person
{
	int a;
	char b;
	char buf[64];
	int d;
};

void test()
{
	struct Person p = { 10,'a',"hello world!",100 };
	char b;
	//b相对于结构体首地址的偏移量
	printf("a off  = %d\n", offsetof(struct Person, b));

	//计算100的偏移量:先对p取地址,然后强制转换成char类型以便控制每字节的偏移量
	//取结构体首地址后加上偏移量就为待求变量的首地址,此时再加上int*表示取后4个字节
	printf("d = %d\n", *(int*)((char*)&p + offsetof(struct Person, d)));
}

在这里插入图片描述

2.指针的间接赋值

在这里插入图片描述

void changeValue(int* p)
{
	//指针和普通变量相似,指针也有内存即地址,也保存着变量
	//唯一不同在于保存的值为地址
	*p = 100;
}

void test()
{
	int a = 10;
	changeValue(&a);//changeValue(a)表示仅把a的值传过去
	printf("%d\n", a);
}

在这里插入图片描述
在这里插入图片描述
先拿到a的固定地址,然后加上int表示把该地址当成指针,计算步长,最后表示解引用即得到a的内存空间
在这里插入图片描述

void changePointer(int **val)
{
	//**val表示内存空间,*val表示该空间内存取的值
	*val = 0x008;
}

void test()
{
	int* p = NULL;
	//&取地址后会加一层指针等级,比如整型a取地址后为int*,*p取地址后为二级指针**p
	changePointer(&p);
	printf("p = %x\n", p);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.指针做形参的输入特性

void printString(const char* str)
{
	printf("打印内容 : %s\n", str+2);
}

void test()
{
	//指针的输入特性,主调函数分配内存,被调函数使用内存
	//堆上分配内存
	char* s = malloc(sizeof(char) * 100);
	memset(s, 0, 100);
	strcpy(s, "hello world!");
	printString(s);//只需要传值,不需要取地址,&代表将要改变s的地址指向另一块空间
}

在这里插入图片描述

void printStringArray(const char** arr, int len)
{
	//arr为char*类型,arr[0] == *(arr+0)
	for (int i = 0; i < len; ++i)
	{
		printf("%s\n", arr[i]);
	}
}

void test()
{
	//栈上分配
	//指针数组,每一个元素都是char*类型的指针
	//数组名做形参会退化为指向数组首元素的指针
	char* strs[] = {
		"aaaaa",
		"bbbbb",
		"ccccc",
		"ddddd",
	};
	int len = sizeof(strs) / sizeof(strs[0]);
	printStringArray(strs, len);
}

在这里插入图片描述

4.指针做形参的输出特性

void allocateSpace(char **temp)
{
	char* p = malloc(100);
	memset(p, 0, 100);
	strcpy(p, "hello world!");

	//指针的间接赋值
	*temp = p;
}

void test()
{
	//输出特性  被调函数分配内存,主调函数使用内存
	char* p = NULL;
	allocateSpace(&p);
	printf("p = %s\n", p);
	if (p != NULL)
	{
		free(p);
		p = NULL;
	}
}

在这里插入图片描述

5.字符串拷贝

字符串是以0或’\0’结尾的字符数组,数字0和字符’\0’等价
在这里插入图片描述
在这里插入图片描述

void copyString01(char* dst, char* source)
{
	int len = strlen(source);
	for (int i = 0; i < len; i++)
	{
		dst[i] = source[i];
	}
	dst[len] = '\0';
}

void test()
{
	char* source = "hello world!";
	//char buf[1024] = { 0 };//如果不初始化,需要在拷贝的数组最后加上'\0'
	char buf[1024];
	copyString01(buf, source);
	printf("%s\n", buf);
}

在这里插入图片描述

void copyString02(char* dst, const char* source)
{
	//指针方式
	while (*source != '\0')
	{
		*dst = *source;
		++dst;
		++source;
	}
	*dst = '\0'; 
}

void test()
{
	char* source = "hello world!";
	//char buf[1024] = { 0 };//如果不初始化,需要在拷贝的数组最后加上'\0'
	char buf[1024];
	copyString02(buf, source);
	printf("%s\n", buf);
}

在这里插入图片描述

void copyString03(char* dst, const char* source)
{
	while (*dst++ = *source++);
}

void test()
{
	char* source = "hello world!";
	//char buf[1024] = { 0 };//如果不初始化,需要在拷贝的数组最后加上'\0'
	char buf[1024];
	copyString03(buf, source);
	printf("%s\n", buf);
}

在这里插入图片描述

6.字符串反转

void reverseString(char* str)
{
	if (NULL == str)
	{
		return;
	}
	int len = strlen(str);int  start = 0;int end = len-1;
	while (start < end)
	{
		char temp = str[start];
		str[start] = str[end];
		str[end] = temp;
		++start; --end;
	}
}

void test()
{
	char p[] = "abc";
	reverseString(p);
	printf("p = %s", p);
}

在这里插入图片描述

void reverseString(char* str)
{
	//指针版
	if (NULL == str)
	{
		return;
	}
	int len = strlen(str);
	char* pStart = str;//首地址
	char* pEnd = str + len - 1;
	while (pStart < pEnd)
	{
		char temp = *pStart;
		*pStart = *pEnd;
		*pEnd = temp;
		pStart++; pEnd--;
	}
}

在这里插入图片描述

7.字符串的格式化—sprintf

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

void test()
{
	//1. 格式化字符串
	char buf[1024] = { 0 };
	sprintf(buf, "hello %s!", "Trump");
	printf(buf);

	//2. 拼接字符串
	char *s1 = "hello";
	char *s2 = "world!";
	memset(buf, 0,1024);
	sprintf(buf, "%s %s", s1, s2);
	printf("\n%s", buf);

	//3. 数字转换成字符串
	int num = 666;
	memset(buf, 0, 1024);
	sprintf(buf, "%d", num);
	printf("\n%s", buf);

	//4. 开辟5个char*的内存空间,并分别命名为name i
	char** p = malloc(sizeof(char*) * 5);
	for (int i = 0; i < 5; ++i)
	{
		p[i] = malloc(64);
		memset(p[i], 0, 64);
		sprintf(p[i], "name_%d", i + 1);
	}
	printf("\n");
	for (int i = 0; i < 5; ++i)
	{
		printf("%s\n", p[i]);
	}
	//释放内存
	for (int i = 0; i < 5; ++i)
	{
		if (p[i] != NULL)
		{
			free(p[i]);
			p[i] = NULL;
		}
	}
	if (p != NULL)
	{
		free(p);
		p = NULL;
	}

	//5. 格式化数字八进制、十六进制
	memset(buf, 0, 1024);
	sprintf(buf, "%o", num);
	printf("八进制:%o", num);
	memset(buf, 0, 1024);
	sprintf(buf, "%x", num);
	printf("\n十六进制:%x", num);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值