并非从0开始的c++之旅 day4
一、指针的步长
- 指针变量+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);
}
字节数主要根据指针类型而改变
- 在解引用的时候,取出的字节数
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*
- 练习
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、间接赋值的三大条件
通过指针间接赋值成立的三大条件:
- 2个变量(一个普通变量一个指针变量、或者一个实参一个形参)
- 建立关系
- 通过*操作指针指向的内存
通过指针找到对应的地址,可以直接修改这个地址的内容,而不需要改变指针
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);