学习总结
1 利用带参宏定义实现信息打印
#include <stdio.h>
#include <stdlib.h>
#define DEVICE_EXAMPLE_TRACE(...) \
do \
{ \
printf("%s.%d: ", __func__, __LINE__); \
printf(__VA_ARGS__); \
} while (0)
int main()
{
DEVICE_EXAMPLE_TRACE("hello world %s,%d,%f\n","112233",2020,11.35);
return 0;
}
注:…表示可变参数列表,__VA_ARGS__在预处理中,会被实际的参数集(实参列表)所替换。
运行结果:
宏定义中的 # 与
-
“#”
作用:用于把宏定义中的参数两端加上字符串的标识:""
示例:#define STR(str) #str
用法:STR(myname)
会被替换成"myname"
注意:一般由任意字符都可以做形参,但以下情况会出错:
STR())
这样,编译器不会把“)”
当成STR()
的参数。
STR(,)
同上,编译器不会把“,”
当成STR
的参数。 -
“##”
作用:连接
示例:#define STR(str) L##str
用法:STR(abc)
会被替换成Labc
代码:
#include <stdio.h>
#include <stdlib.h>
#define testMarco(evt, cb) Marco_##evt(cb)
void Marco_ABC(int temp)
{
printf("welcome enter Marco_ABC,temp = %d\n",temp);
}
void Marco_123(int temp)
{
printf("welcome enter Marco_123,temp = %d\n",temp);
}
int main()
{
testMarco(ABC, 1111);
testMarco(123, 2222);
return 0;
}
运行结果:
大小端模式与内存越界
栈的高地址在上,低地址在下,大小端都这样。
int main(int argc, char* argv[]){
int i = 0;
int arr[3] = {0};
for(; i<=3; i++){
arr[i] = 0;
printf("hello world\n");
}
return 0;
}
结果:这段代码的运行结果并非是打印三行“hello word”,而是会无限打印“hello world”,这是为什么呢?
因为,数组大小为 3,a[0],a[1],a[2],而我们的代码因为书写错误,导致 for 循环的结束条件错写为了 i<=3 而非 i<3,所以当 i=3 时,数组 a[3]访问越界。
我们知道,在 C 语言中,只要不是访问受限的内存,所有的内存空间都是可以自由访问的。a[3]会被定位到某块不属于数组的内存地址上,而这个地址正好是存储变量 i 的内存地址(栈的高地址在上,低地址在下,i在高地址),那么 a[3]=0 就相当于 i=0,所以就会导致代码无限循环。
memcpy 与 memmove 的区别
概述
memcpy和memmove都是C语言的库函数,在头文件string.h中,作用是内存拷贝,原型如下:
void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
相同点
它们的作用都是内存拷贝;
不同点
-
当内存发生局部重叠时,memmove保证了拷贝的结果是正确的,但是memcpy不一定是正确的。但是memcpy比memmove速度快。
-
memcpy函数从src内存中拷贝了count字节到dest内存区域,但是src和dest的内存区域不能重叠。
-
memcpy函数从src内存中拷贝了count字节到dest内存区域,但是src和dest的内存区域可以重叠。
对比
memcpy和memmove对比:
内存重叠区域有两种情况:
函数实现
- memcpy
void *my_memcpy(void *dst,void *src,size_t n)
{
char *tmp = (char *)dst;
char *p = (char *)src;
while(n--)
{
*tmp++ = *p++;
}
return dst;
}
memcpy在第二种内存覆盖情况下,最终不会得到正确的结果,会有踩内存现象,第一种内存覆盖可以得到正确的结果。
- memmove
void *my_memmove(void *dst,void *src,size_t n)
{
char *p1 = (char *)dst;
char *p2 = (char *)src;
if(p1 > p2 && p2+n > p1)//对于第二种内存覆盖进行了讨论
{
p1 = p1+n-1;
p2 = p2+n-1;
while(n--)
{
*p1-- = *p2--;
}
}
else
{
while(n--)
{
*p1++ = *p2++;
}
}
return dst;
}