C内存分配的注意点
C语言的内存分配,有很多的注意点。
1. int 的大小问题。int 在不同的编译器下大小是不一样的。在tc下是2位,在 vc 下,和 long 一样,是4位。
2. memset 不是用来分配内存的,而是设置某个区域的内存为某个值,这个内存区域必须是可以修改的,
而且是已经分配好了的。
这个函数的原型为:
void * memset(void * _Dst, int _Val, size_t _Size);
第二个参数是int 实际上有些迷惑人。如果你输入了一个大于 256 的数,就会被截断了。只截取一个字节的数据。
先看下面的代码:
Hello World.
After memset.
11llo World.
但是,下面的就不对了:
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
After memset.
16843009 16843009 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
这里只拷贝了两个字节。
实际上,因为memset是逐字节拷贝,一个int 有 4个字节,这样
16843009 = 00000001000000010000000100000001。占用了4次拷贝了。
所以,对非char 类型的结构进行 memset 的时候,最好用 0, 或者 -1
0 在计算机内部表示 是 0x00000000
-1 在计算机内部的表示是 0xffffffff
其他的值的初始化基本上没有意义。
3. 对齐要求
下面这个结构体占用几个字节呢?
struct charintsize
{
int a;
char b;
};
答案是 8个,因为结构体有一个对齐原则。具体的,不需要知道怎么对齐,只要知道,不能简单的加和,而要用 sizeof 计算。
1. int 的大小问题。int 在不同的编译器下大小是不一样的。在tc下是2位,在 vc 下,和 long 一样,是4位。
2. memset 不是用来分配内存的,而是设置某个区域的内存为某个值,这个内存区域必须是可以修改的,
而且是已经分配好了的。
这个函数的原型为:
void * memset(void * _Dst, int _Val, size_t _Size);
第二个参数是int 实际上有些迷惑人。如果你输入了一个大于 256 的数,就会被截断了。只截取一个字节的数据。
先看下面的代码:
char
s[]
=
"
Hello World.
"
;
system( " cls " );
printf( " Before memset.\n " );
printf( " %s\n " , s);
memset(s, '1' , 2 );
printf( " After memset.\n " );
printf( " %s\n " ,s);
Before memset.
system( " cls " );
printf( " Before memset.\n " );
printf( " %s\n " , s);
memset(s, '1' , 2 );
printf( " After memset.\n " );
printf( " %s\n " ,s);
Hello World.
After memset.
11llo World.
但是,下面的就不对了:
int
s[
8
];
system( " cls " );
printf( " Before memset.\n " );
for ( int i = 0 ; i < 8 ; i ++ ) {
printf( " %d " , s[i]);
}
putchar( ' \n ' );
memset(s, 1 , 8 );
printf( " After memset.\n " );
for ( int i = 0 ; i < 8 ; i ++ ) {
printf( " %d " , s[i]);
}
Before memset.
system( " cls " );
printf( " Before memset.\n " );
for ( int i = 0 ; i < 8 ; i ++ ) {
printf( " %d " , s[i]);
}
putchar( ' \n ' );
memset(s, 1 , 8 );
printf( " After memset.\n " );
for ( int i = 0 ; i < 8 ; i ++ ) {
printf( " %d " , s[i]);
}
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
After memset.
16843009 16843009 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
这里只拷贝了两个字节。
实际上,因为memset是逐字节拷贝,一个int 有 4个字节,这样
16843009 = 00000001000000010000000100000001。占用了4次拷贝了。
所以,对非char 类型的结构进行 memset 的时候,最好用 0, 或者 -1
0 在计算机内部表示 是 0x00000000
-1 在计算机内部的表示是 0xffffffff
其他的值的初始化基本上没有意义。
3. 对齐要求
下面这个结构体占用几个字节呢?
struct charintsize
{
int a;
char b;
};
答案是 8个,因为结构体有一个对齐原则。具体的,不需要知道怎么对齐,只要知道,不能简单的加和,而要用 sizeof 计算。