目录
2、测试:memset格式化字符,sprintf格式化字符串
一、目的
1、想多学习C知识
二、参考
1、(01)某马C++24期完整版
三、操作:01函数调用流程
1、测试1:使用宏函数进行计算
①总结:宏函数,不是一个真正的函数(只是预处理进行简单的文本替换)
②总结:宏函数多写括号
1、测试2:真正的函数进行计算
①总结:这个才是真正的函数 返回值 参数 函数体
1、测试3:以空间换时间
①总结:对于频繁使用并且短小的函数,我们一般使用宏函数替换,因为宏函数没有普通函数调用的开销(函数压栈、跳转、返回等)
四、操作:02 变量传递分析(源码没有暂时没有操作)
五、操作:03 栈的生长方向
1、测试1:
①运行结果:
①疑问(已解答):为什么a先创建的但是输出时候地址却是排在后面?
a、答:栈底一般都是在高地址,栈顶在低地址
①疑问(已解答):为什么连续定义的int变量,地址为什么相差12个字节?
答:
b、答:int类型:4个字节;int址:4个地址
答b:为了验证,我创建了double变量并且输出查看。double类型:8个字节;double地址:8个地址
六、操作:04 内存存放方向
1、测试1:因为课程源码就有了问题,所以没有练习
七、操作:05 指针步长
1、(疑问-未解决)测试1
①运行结果
②疑问:为什么最终输出的是100?
a、答:因为buf+1的地址是buf后面,加入buf地址是0,那么buf+1地址就是1024了,因为buf占了1024个字节;buf+1的内容是100,因为a地址给了buf+1了。
八、操作:06 指针的间接赋值
1、测试1:
①运行结果
①总结:test01中将变量a的地址传递给changeValue,changeValue中对a的地址进行操作,a变量在test01函数结束后,才会被系统收回,因为在栈中;所以最终操作的是a这个地址上面的内容,因此a的内容变了
1、测试2:形参是二级指针,修改指针地址
①运行结果:会报错:原来是课程源码是c,而我的是cpp文件,因此一些操作在c++中不支持
①运行结果:
- a、总结:因为p是int指针类型的变量,将其指针地址传递给了changePointer函数中。changePointer函数中,接受到了*p的地址(int **val二级指针就是接受到了*val的地址),然后对*val这个地址进行操作,
- b、总结:看清楚是对地址上面的数据进行操作,还是对地址进行操作
- c、总结:指针=地址=门牌号=0x16进制 ;
- d、*p局部变量会在test02函数生命周期结束后销毁。
九、操作:07 指针的输入和输出特性
十、操作:08 字符串操作
1、测试:输出字符数组
①运行结果:
- a、总结:#include <iostream>//c文件时候不能添加此文件
- .h文件是c语言时候的头文件,c++语言是没有.h后缀
- C语言中没有字符串:所以使用字符数组;字符数组=字符串
- 字符数组以\0结束
2、测试:for循环拷贝字符数组
①运行结果
- 总结:字符数组以\0结束
- 总结:因为buf[]字符数组=指针,指针地址是字符数组第一个字符地址,所以可以作为参数传递给copyString01函数中
- 总结:*source 和buf[1024]是局部变量,并且将地址传递给了copyString01,所以当test02函数运行结束,*source 和buf[1024]才会被系统收回(创建在栈上面)
- 总结:for循环将当前字符数组每一个的字符传递给另一个字符数组的每一个字符
3、(有疑问-已解决)测试:while循环拷贝字符数组
①运行结果
- 总结:while循环中只要不是\0(也就是字符数组没有结束),就一直将*source指针步长传递给*dst指针步长,然后指针步长要++。
- 总结:
①疑问:为什么while循环里面通过前缀++来到下一个字符?
答:因为你传递copyString02的buf、source参数是字符数组,然后dst、source是字符指针=地址,所以++其实是地址挪后一个
4、测试:while循环赋值字符数组
①运行结果
- 总结:判断字符是不是为空,也就是是不是字符数组结束了,NULL==‘\0’
- 总结:后缀++,先执行赋值,再执行指针步长++
- 总结:NULL=='\0'
5、测试:字符串反转(某软面试题)
①运行结果:
- 总结:传递的参数*str输出是a
- 总结:#if 0 #else #endelse =注释
- 总结:字符数组,里面的序列,通过while循环来不断地变化
- 总结:#if 0 中:反转的话,一定要有个临时变量temp来接受开头的元素,然后最后的元素赋值给开头的元素,然后临时变量将数值赋值给最后的元素;然后++start,--end
- 总结:#if 0 :是通过字符数组str[start],str[end]来进行赋值
- 总结:字符数组,
#include <stdlib.h>
#include <stdio.h>
void reverseString(char *str)
{
if (NULL==str)
{
return;
}
int len = strlen(str);
printf("*str=%c\n",*str);
#if 0
int start=0;
int end=len-1;
while (start<end)
{
char temp = str[start];
str[start] = str[end];
str[end] = temp;
++start;
--end;
}
#else
char * pStart = str;
char *pEnd = str + len - 1;
while (pStart<pEnd)
{
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;
++pStart;
--pEnd;
}
#endif
}
//测试3:字符串反转
void test03()
{
char p[] = "abc";
reverseString(p);
printf("p=%s\n", p);
}
int main()
{
test03();
system("pause");
return EXIT_SUCCESS;
}
6、测试:字符数组赋值
①运行结果:
- 总结:while循环来进行赋值
- 总结:*p是字符数组里面的序列号,while每次循环后,执行下一步,得到数组里面的下一个字符
- 总结:好像没有free(temp)
- p是char*类型,那么*p是?
①运行结果
- 总结:src是指针,所以输出时候用8、十、16进制的输出
- 总结:&src为什么是?
- 总结:*src就是字符数组
十一、操作:09 格式化字符串_sprintf
1、测试:sprintf进行格式化字符串
①运行结果:
- 总结:sprintf的用法
- 总结:char设置为0,还可以使用sprintf进行格式化
2、测试:memset格式化字符,sprintf格式化字符串
①运行结果:
- 总结:注意memset、sprintf用法
①总结:memset用法
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
①总计:sprintf用法
sprintf指的是字符串格式化命令,函数声明为 int sprintf(char *string, char *format [,argument,...]);,主要功能是把格式化的数据写入某个字符串中,即发送格式化输出到 string 所指向的字符串。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。解决这个问题,可以考虑使用 snprintf函数,该函数可对写入字符数做出限制
1、测试:数字转换为字符串格式
①运行结果
①总结:使用memset进行字符格式化
①总结:sprintf进行字符串格式化
1、测试:格式化数字八进制 十六进制
①运行结果:
①总结:%o:八进制 %x:十六进制
1、(有疑问-)测试:malloc和free申请、释放内存
①运行结果
①总结:释放内存:每一个malloc都要free
②总结:为什么使用二级指针?
a、char *p是字符数组=字符串;char **p 是指向这个字符数组的指针?