内存管理
内存中的存储空间
BSS段:未初始化或初始化为0的全局变量、静态变量。(“Block Started by Symbol”的缩写,意为“以符号开始的块”)
数据段(data):已初始化的全局变量、静态变量
堆(heap):malloc分配的内存,(堆的生长方向,与栈相反,堆是由低地址向高地址增长)
栈(stack):函数内的局部变量,(栈的生长方向是由高地址向低地址生长;栈中的数组,是一次性分配一块固定内存,然后数组内的元素是由低地址向高地址生长)
代码段(text):该部分内存通常只读。字符串常量也属于代码段;可执行的部分如函数
大小端
CPU中的两种存储方式:
大端 : 数据的高位字节在内存的低地址;
小端 : 跟大端相反——高位字节在内存的高地址(即大在大,小在小);
eg.
32位int型数0x12345678,最高有效字节为0x12,最低有效字节为0x78。
内存地址:
低 高
大端 0x12 0x34 0x56 0x78 (从地址低到高,按顺序存放)
小端 0x78 0x56 0x34 0x12
EOF
ASCII码取值范围时0-127,所以可以取-1(EOF)来标志文件结束。EOF为int型,占4个字节。
退出
异常退出
abort() //检测到异常,退出进程
eg.
C:
/*
*输出:
*Be about to abort....
*
*Aborted (core dumped)
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Be about to abort....\n");
abort();
puts("This will never be executed!/n");
exit(EXIT_SUCCESS);
}
assert //可以用来检测空指针异常
eg.
C:
/*
*此文件文件名为test.c
*执行结果:
*
*Assert failed: test.c, func Test,line 30
*Aborted (core dumped)
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void Assert(char *filename, const char *func, unsigned int lineno);
#define ASSERT(condition)\
do{ \
if(condition)\
NULL; \
else\
Assert(__FILE__, __FUNCTION__, __LINE__);\
}while(0)
void Assert(char *filename, const char *func, unsigned int lineno)
{
fflush(stdout);
fprintf(stderr, "\nAssert failed: %s, func %s,line %u\n", filename, func, lineno);
fflush(stderr);
abort();
}
void Test(unsigned char *str)
{
ASSERT(str != NULL); //这是第30行
}
int main(void)
{
Test(NULL);
return 0;
}
define和typedef
define 是简单的文本替换
typedef是类型的重命名
eg.
#define T1 struct foo *
T1 a, b;
该声明展开后为 struct foo * a, b;
这里a是指向结构的指针,b是一个结构(不是指针)。
typedef struct foo *T2;
T2 a, b;
这里T2是个真实的类型,而不是文本替换。该声明展开后,a是指向结构的指针,b是指向结构的指针。
NULL
NULL存在内存位置0。NULL不指向任何对象。
eg.
C:
/*
*test.c
*/
#include <stdio.h>
int main(void)
{
char *p;
p = NULL;
printf("Location 0 is %s\n", *p);
}
执行结果:
[^_^ 12:56 270]$gcc -o test1 test1.c
[^_^ 12:56 271]$./test1
Segmentation fault (core dumped)
上面的现象说明该机器禁止读位置为0的内容,对内存位置0强加了硬件级的读保护。所以出现段错误。
当然有些编译器,对内存位置0可读,这种情况下读出来的是垃圾信息。
有些编译器,对内存位置0可读可写,这种情况下,很有可能覆盖操作系统的部分内容,造成彻底的灾难。
printf 中的 % 和 %%,%o和%#o ,%p
% 和 %%
% : 用来格式化输出数据;
%% : 用来输出一个%,(printf中用%%来输出一个%,而不是%来输出一个%)
%o 和 %#o
%o : 八进制的格式打印数据
%#o : 八进制的格式打印数据,在数据前加上八进制标记0
eg.
C:
#include <stdio.h>
int main(void)
{
printf("%o, %#o, \n", 10, 10); //八进制的格式打印数据
printf("%x, %#x, \n", 10, 10); //十六进制的格式打印数据
}
输出结果
[^_^ 16:04 294]$./test
12, 012,
a, 0xa,
%p
%p : 用于打印指针所指向的地址