安装netmap
参考网站:安装教程
字符转mac地址
方法1:
#include <stdio.h>
#include <string.h>
#define ETH_ALEN 6
#define NTY_SELF_MAC "00:0c:29:58:6f:f4"
int str2mac(char *mac, char *str) {
char *p = str;
unsigned char value = 0x0;
int i = 0;
while (*p != '\0') { // '\0'可以作为字符串的结束标识字符
if (*p == ':') {
mac[i++] = value;
value = 0x0;
} else {
unsigned char temp = *p;
if (temp <= '9' && temp >= '0') {
temp -= '0';
} else if (temp <= 'f' && temp >= 'a') {
temp -= 'a';
temp += 10;
} else if (temp <= 'F' && temp >= 'A') {
temp -= 'A';
temp += 10;
} else {
break;
}
value <<= 4; //不断对vlaue的左移动四位(保证value永远为0x00)
value |= temp;
}
p ++;
}
mac[i] |= value;
return 0;
}
void print_mac(unsigned char *mac) { //unsigned char很关键
int i = 0;
for (i = 0;i < ETH_ALEN-1;i ++) {
printf("%02x:", mac[i]);
}
printf("%02x", mac[i]);
}
struct arphdr {
unsigned char smac[ETH_ALEN];
};
int main() {
struct arphdr arph;
//结构体初始化
bzero(&arph, sizeof(struct arphdr));
str2mac(arph.smac, NTY_SELF_MAC);
print_mac(arph.smac);
return 0;
}
输出的结果:00:0c:29:58:6f:f4
方法2:
#include <stdio.h>
#include <string.h>
static int hex2num(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
void hexstr2mac(char *dst, char *src) {
int i=0;
while(i<6) {
if(' ' == *src||':'== *src||'"'== *src||'\''== *src) {
src++;
continue;
}
*(dst+i) = ((hex2num(*src)<<4)|hex2num(*(src+1)));
i++;
src += 2;
}
}
void print_mac(unsigned char *mac) { //使用unsigned char很关键,保证正产输出
int i = 0;
for (i = 0;i < 5;i ++) {
printf("%02x:", mac[i]);
}
printf("%02x", mac[i]);
}
int main(){
char mac[6]={0};
char* macstr="AA:BB:CC:DD:EE:FF";
hexstr2mac(mac,macstr);
print_mac(mac);
return 0;
}
补充内容
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct S{
int d;
char name[4];
};
int main(){
struct S *dd =malloc(sizeof(struct S)); //指针分配空间,有void*->struct S *dd的过程
memset(&(dd->d), 0, sizeof(int));
//memset(dd->name, 0, sizeof(8));
dd->name[0]='0';
dd->name[1]='1';
dd->name[2]='2';
dd->name[3]='3';
printf("dd->d=%d,dd->d=0x%08x\n",dd->d,&(dd->d));
printf("dd->name=0x%08x\n",dd->name);
printf("&(dd->name)=0x%08x\n",&(dd->name));
printf("&(dd->name[1])=0x%08x\n",&(dd->name[1]));
printf("&(dd->name[2])=0x%08x\n",&(dd->name[1]));
printf("&(dd->name[3])=0x%08x\n",&(dd->name[3]));
printf("dd->name[1]=%d\n",dd->name[1]);
printf("dd->name[2]=%d\n",dd->name[2]);
return 0;
}
输出的结果:
dd->d=0,dd->d=0x14e4f2a0
dd->name=0x14e4f2a4
&(dd->name)=0x14e4f2a4
&(dd->name[1])=0x14e4f2a5
&(dd->name[2])=0x14e4f2a5
&(dd->name[3])=0x14e4f2a7
dd->name[1]=49
dd->name[2]=50
动态开辟内存的几种方式
C语言动态开辟的管理方式(malloc,calloc,realloc)
相同点:
- 都是C语言的库函数,在使用时都必须包含相应的头文件
- 都是从堆上申请空间,使用完成时必须要通过free来进行释放,否则,内存泄漏
- 申请空间成功后,返回空间的首地址,申请失败返回NULL,因此在使用时必须判空
- 返回值类型为void*,在使用时要进行强制类型转化
注意事项:(1)malloc申请的内存,一旦申请成功,就只能为你所用,其他地方的malloc无法申请到这块内存;(2)free释放内存后,这块内存重获自由,程序其他地方调用malloc,有可能系统会把这块内存分配出去;(3)free释放内存后,这块内存里面的数据有可能变成垃圾值,有可能还是原来的数值,当然也有可能无法访问。
free释放掉内存后,应该将指针置为空,避免乱用,被free掉的内存不要再去使用它,虽然有时候使用不会报错,如果进程终结, 对应的堆内存自动被回收, 不会泄露(解释malloc,不需要free也可以,程序结束,进程资源释放)。
不同点:
malloc:
#include<stdlib.h>
#include<malloc.h>
void *malloc( size_t size ); //注意指针函数
malloc只是开空间,参数是要申请空间的字节大小
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
void main( void )
{
int *buffer;
size_t size;
buffer = (int *)malloc( 1000 * sizeof( int ) ) //动态开辟内存
//对开辟的内存进行判断
if( buffer == NULL )
printf( "Can't allocate memory\n" );
if( buffer != NULL )
printf( "Allocated 1000 int integers\n" );
free( buffer );
}
calloc:
#include <malloc.h>
#include <stdlib.h>
void *calloc( size_t num, size_t size );
1.开辟空间后空间会被初始化为0.(这个很关键)
2.参数有两个,一个是申请元素的个数num,另一个表示单个元素类型的大小size
#include <stdio.h>
#include <malloc.h>
void main( void )
{
long *buffer;
buffer = (long *)calloc( 40, sizeof( long ) );
if( buffer != NULL )
printf( "Allocated 40 long integers\n" );
else
printf( "Can't allocate memory\n" );
free( buffer );
}
realloc:
#include <malloc.h>
#include <stdlib.h>
void *realloc( void *memblock, size_t size );
realloc是进行空间大小调整的操作。(新的大小要大于原来的大小,否则会导致数据丢失)
功能:先判断当前的指针是否有足够的连续空间,如果有,扩大memblock指向的地址,并且将memblock返回,如果空间不够,先按照size指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来memblock所指内存区域(注:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
注意事项:
1.如果memblock为NULL,则realloc()和malloc()类似。分配一个size的内存块,返回一个指向该内存块的指针。
2.如果size大小为0,那么释放memblock指向的内存,并返回NULL。
3.如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回NULL。而原来的内存块保持不变。
int main ()
{
int* p2 = (int*)calloc(4, sizeof (int));
//通过realloc来扩大p2的空间,并把新的地址赋值给p3
int* p3 = (int*)realloc(p2, sizeof(int)*10);
free(p3 );
return 0;
}
结论:
1.realloc失败的时候,返回NULL
2.realloc失败的时候,原来的内存不改变,不会释放也不会移动
3.假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址
4.如果size为0,效果等同于free()。(对指针本身进行释放)
5.传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的
6.传递给realloc的指针可以为空,等同于malloc。
C语言动态开辟内存模板
struct callbacks {
void (*log_fatal)(void *logger, const char *file, int line,
const char *function, const char *format, ...)
__attribute__((format(printf, 5, 6)));
};
static void log_fatal(void *logger, const char *file, int line,
const char *function, const char *format, ...)
{
va_list argp;
va_start(argp, format);
logging(file, line, function, FATAL, format, argp);
va_end(argp);
}
#define LOG_FATAL(cb, fmt, args...) \
(cb)->log_fatal((cb)->logger, __FILE__, __LINE__, __func__, fmt, ##args)
#define PLOG_FATAL(cb, fmt, args...) \
LOG_FATAL(cb, fmt ": %s", ##args, strerror(errno))
typedef unsigned long size_t
void *calloc_or_die(size_t nmemb, size_t size, struct callbacks *cb)
{
void *ptr = calloc(nmemb, size); //初始化状态为0
if (!ptr)
PLOG_FATAL(cb, "calloc"); //打印日志创建不成功
return ptr;
}
struct flow *f = calloc_or_die(1, sizeof(struct flow), t->cb); //调用函数,t->cb回调函数,打印log日志
C++语言动态内存开辟的管理方式
new和delete
注:C++兼容C语言,所以C语言内存管理方式在C++中可以继续使用,但是有了C++机制的关键字,优先使用C++的关键字。
申请内置类型空间:
void Test()
{
// 动态申请一个int类型的空间
int* ptr4 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10); //注意是圆括号
delete ptr4; //注意释放的方式
delete ptr5;
//管理对象组
// 动态申请3个int类型的空间
int* ptr6 = new int[3]; //注意是方括号
delete[] ptr6; //注意释放的方式
}
class Test
{
public:
Test(): _data(0)
{
cout<<"Test():"<<this<<endl;
}
~Test()
{
cout<<"~Test():"<<this<<endl;
}
private:
int _data;
}
void Test1()
{
//C语言动态开辟内存
//申请一个Test类型空间
Test *p1=(Test*)malloc(sizeof(Test)); //1个
free(p1);
//申请10个Test类型空间
Test *p2=(Test*)malloc(sizeof(Test)*10); //10个
free(p2);
}
void Test2()
{
//C++语言动态开辟内存
//申请一个Test类型的空间并初始化为10
Test *p2=new Test(10); //注意赋值 1个
delete p2;
//申请10个Test类型的空间
Test *p3=new Test[10]; //10个
delete[] p3;
}
在申请自定义类型的空间时,new会自动调用构造函数,delete会自动调用析构函数
**注意事项:**申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和 delete[],搭配使用,避免出错。(对于内置类型来说,new[]开辟的空间用delete来释放程序不会崩溃,因为内置类型的空间开辟和释放不会调用构造函数和析构函数)
malloc/free和new/delete的异同点
malloc/free和new/delete的共同点是:
都是从堆上申请空间,并且需要用户手动释放
malloc/free和new/delete不同的地方是:
1.malloc和free是函数,new和delete是操作符
2.malloc申请的空间不会初始化,new可以初始化(很关键)
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
4.malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常(健壮性代码一定要对new开辟的内存进行抛异常处理)
6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
堆与栈的区别
1.堆空间的内存是动态分配的,一般存放对象,并且需要手动释放内存。需要程序员自己申请并且指明大小,如C语言的malloc函数。
2.栈空间的内存由系统自动分配,一般存放局部变量等,不需要手动管理内存。例如声明函数中的一个局部变量int b,系统在栈中自动为b开辟空间。
- [1] 管理方式:
对于栈来讲,由编译器自动管理,无需我们手动控制。
对于堆来说,释放工作由程序员控制,容易产生memory warning。 - [2]申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域.即栈顶的地址和栈的最大容量是系统预先规好的。栈的大小是1M,如果申请空间超过栈的剩余空间时,将提示overflow.因此,能从栈获得的空间较小。(linux可以通过ulimit等命令查看)
堆:堆是向高地址扩展的数据结构,是不连续的内存区域.这是因为系统是用链表来存储空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址.堆得大小受限于计算机系统中有效地虚拟内存.由此可见,堆获得的空间比较灵活,也比较大。 - [3] 碎片问题:
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。
对于栈来讲,则不会存在这个问题,因为栈是先进后出得队列,它们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。 - [4]分配方式:
堆都是动态分配的,没有静态分配的堆。
栈有两种分配方式:静态分配和动态分配.静态分配是编译器完成的,比如局部变量的分配.动态分配由alloc函数进行分配,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放,无需我们手工实现,静态变量是不入栈的。 - [5]分配效率:
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
堆则是C/C++函数库提供的,它的机制是很复杂的。例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
为什么栈比堆快?
从两方面来考虑:
1.分配和释放,堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞,碎片),这些都会花费一定的时间,具体可以看看MALLOC和FREE的源代码,他们做了很多额外的工作,而栈却不需要这些(有专门的系统指令)。
2.访问时间,访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。另外,堆的内容被操作系统交换到外存的概率比栈大,栈一般是不会被交换出去的。