并非从0开始的c++之旅 day4

一、指针的步长

  1. 指针变量+1后跳跃的字节数
void test01() {
	char* p = NULL;

	printf("%d\n", p);
	printf("%d\n", p+1);

	double* p2 = NULL;

	printf("%d\n", p2);
	printf("%d\n", p2 + 1);
}

字节数主要根据指针类型而改变

  1. 在解引用的时候,取出的字节数
void test02() {
	char buf[1024] = { 0 };
	int a = 1000;
	memcpy(buf+1, &a, sizeof(int));

	char* p = buf;
	printf("%d\n", *(int*)(p+1));
}

memcpy可以复制a到buf的相应位置,若要访问该位置,需要在解引用p指针的时候,强制类型转换为int*

  1. 练习
void test03() {
	struct Person p = { 'a',10,"hello world",1000 };
	
	//p中的d属性偏移量是多少?
	printf("d的偏移量为:%d\n", offsetof(struct  Person, d));

	printf("d 的值为:%d\n", *(int*)((char*)&p+ offsetof(struct  Person, d)));
}

offsetof可以得到访问属性的偏移量,需要头文件

#include < stddef.h >

二、间接赋值

1、间接赋值的三大条件

通过指针间接赋值成立的三大条件:

  1. 2个变量(一个普通变量一个指针变量、或者一个实参一个形参)
  2. 建立关系
  3. 通过*操作指针指向的内存

通过指针找到对应的地址,可以直接修改这个地址的内容,而不需要改变指针

void changeVaule(int * p) {
	*p = 1000;
}

void test02() {
	int a = 10;


	changeVaule(&a);

	printf("%d\n", a);

	printf("%d\n", &a);
}

2、间接赋值的推论

即用n级指针形参,去间接修改了n-1级指针(实参)的值

3、指针做函数参数

指针做函数参数,具备输入和输出特性:

  • 输入:主调函数分配内存
  • 输出:被调用函数分配内存

输入特性

在主调函数分配内存,被调函数使用

在栈上分配内存

void func(char* p) {
	strcpy(p, "hello world");
}

void test01() {
	//在栈上分配内存
	char buf[1024] = { 0 };
	func(buf);

	printf("%s\n", buf);
}

在堆上分配内存

void printString(char* str) {
	printf("%s\n", str);
}

void test02() {
	//在堆区分配内存
	char* p = malloc(sizeof(char) * 64);
	memset(p, 0, 64);
	
	strcpy(p, "hello world");

	//在被调函数中 输出hello world
	printString(p);

	free(p);
	p = NULL;
}

输出特性

在被调函数中分配特性

在被调函数中,分配在堆区内存
主调函数中打印内存内容

void allocatSpace(char** p) {
	char* temp = malloc(sizeof(char) * 64);
	memset(temp, 0, 64);
	strcpy(temp,"hello c");

	*p = temp;
}

void test03() {
	char* p = NULL;
	allocateSpace(&p);

	printf("%s\n", p);
}

三、字符串指针强化

1、字符串注意事项

1、字符串初始化结尾要加\0,否则打印出来结尾会是乱码

void test01() {
	char str1[] = { 'h','e','l','l','o' ,'\0'};

	printf("%s\n", str1);
}

2、字符数组部分初始化,剩余填0,不会出现乱码

	char str2[100] = { 'h','e','l','l','o' };

	printf("%s\n", str2);

3、如果以字符串初始化,那么编译器默认会在字符串尾部添加"\0"


char str3[] = "hello";
printf("%s\n", str3);
printf("sizeof str:%d\n", sizeof(str3));
printf("strlen str:%d\n", strlen(str3));
  • sizeof 计算数组大小,数组包含‘\0’字符,这是数值为6
  • strlen 计算字符串的长度,到‘\0’结束,这里数值为5

4、练习

char str4[100] = "hello";
printf("sizeof str4:%d\n", sizeof(str4));
printf("strlen str4:%d\n", strlen(str4));

char str5[] = "hello\0wrold";
printf("%s\n", str5);
printf("sizeof str5:%d\n", sizeof(str5));
printf("strlen str5:%d\n", strlen(str5));

char str6[] = "hello\012wrold";
printf("%s\n", str6);
printf("sizeof str6:%d\n", sizeof(str6));
printf("strlen str6:%d\n", strlen(str6));
  • 4:100 5
  • 5:11 5
  • 6:11 12
  • \012 输出为换行,\0 意味着8进制

2、字符串拷贝

我们这里提供三种方法

方法一,利用下标的方式拷贝

void copyString01(char* dest, char* source) {
	//利用下标的方式拷贝
	int len = strlen(source);
	for (int i = 0; i < len; i++) {
		dest[i] = source[i];
	}

	dest[len] = '\0';
}

方法二,利用字符串指针

void copyString01(char* dest, char* source) {
	//利用字符串指针
	while (*source != '\0') {
		*dest = *source;

		dest++;
		source++;
	}

	*dest = '\0';
}

方法三,方法二的简化

void copyString03(char* dest, char* source) {
	while (*dest++ = *source++) {
	}
}

3、字符串翻转

我们这里用两种方法

方法一,利用下标方式进行翻转

void reverseString1(char* str) {
	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 reverseString2(char* str) {
	int len = strlen(str);
	char* start = str;//指向第一个字符的指针

	char* end = str + len - 1;//指向最后一个字符的指针

	while (start < end) {
		//交换首尾下标元素
		char temp = *start;
		*start = *end;
		*end = temp;

		start++;
		end--;
	}
}

4、字符串的格式化

也就是sprintf的使用

1、sprintf的基础使用

void test01() {
	char buf[1024];
	memset(buf, 0, 1024);

	//参数1 格式化后目标字符串
	//参数2 格式化形式
	//参数3.。。 格式化中的参数
	sprintf(buf, "今天是%d年 %d月 %d日\n", 2023, 2, 16);

	printf("%s\n", buf);
}

2、拼接字符串

memset(buf, 0, 1024);
char str1[] = "hello";
char str2[] = "world";
int len = sprintf(buf, "%s %s", str1, str2);
//返回值是strlen的结果
printf("buf:%s len:%d\n", buf, len);

//设置宽度 右对齐
memset(buf, 0, 1024);
int num = 100;
sprintf(buf, "%8d", num);
printf("buf:%s\n", buf);


//设置宽度 左对齐
memset(buf, 0, 1024);
int num = 100;
sprintf(buf, "%-8d", num);
printf("buf:%s\n", buf);


//转成16进制字符串 小写
memset(buf, 0, 1024);
int num = 100;
sprintf(buf, "0x%x", num);
printf("buf:%s\n", buf);

//转成8进制字符串
memset(buf, 0, 1024);
int num = 100;
sprintf(buf, "%d", num);
printf("buf:%s\n", buf);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值