14. C语言&数据结构与算法(99道)***3***
3.内存管理&编程题(20道)
3.1由gcc编译的C语言程序占用的内存分为哪几个部分?
| 栈区(stack) |
存放函数的参数、局部变量。 |
| 堆区(heap) |
提供程序员动态申请的内存空间。 |
| 全局(静态)区(static) |
存放全局变量和静态变量,初始化不为0的全局变量和静态变量、const型常量在一块区域(.data段),未初始化的、初始化为0的全局变量和静态变量在相邻的另一块区域(.bss段)。 |
| 程序代码区 |
存放函数体的二进制代码和字符串常量。 |
如何判读一个系统的大小端存储模式?
(1)方法一:int *强制类型转换为char *,用“[]”解引用
void checkCpuMode(void)
{
int c = 0x12345678;
char *p = (char *)&c;
if(p[0] == 0x12)
printf("Big endian.\n");
else if(p[0] == 0x78)
printf("Little endian.\n");
else
printf("Uncertain.\n");
}
(2)方法二:int *强制类型转换为char *,用“*”解引用
void checkCpuMode(void)
{
int c = 0x12345678;
char *p = (char *)&c;
if(*p == 0x12)
printf("Big endian.\n");
else if(*p == 0x78)
printf("Little endian.\n");
else
printf("Uncertain.\n");
}
(3)方法三:包含short跟char的共用体
void checkCpuMode(void)
{
union Data
{
short a;
char b[sizeof(short)];
}data;
data.a = 0x1234;
if(data.b[0] == 0x12)
printf("Big endian.\n");
else if(data.b[0] == 0x34)
printf("Little endian.\n");
else
printf("uncertain.\n");
}
3.3全局变量和局部变量的区别?
(1)全局变量储存在静态区,进入main函数之前就被创建,生命周期为整个源程序。
(2)局部变量在栈中分配,在函数被调用时才被创建,在函数退出时销毁,生命周期为函数内。
3.4以下程序中,主函数能否成功申请到内存空间?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getmemory(char *p)
{
p = (char *)malloc(100);
strcpy(p, "hello world");
}
int main()
{
char *str = NULL;
getmemory(str);
printf("%s\n", str);
free(str);
return 0;
}
答案:不能。
解读:getmemory(str)没能改变str的值,因为传递给子函数的只是str的复制值NULL,main函数中的str一直都是 NULL。正确的getmemory()如下:
①传递的是二重指针,即str的指针
void getmemory(char **p)
{
*p = (char *)malloc(100);
strcpy(*p, "hello world");
}
②传递的是指针别名,即str的别名,C++中
void getmemory(char * &p)
{
p = (char *)malloc(100);
strcpy(p, "hello world");
}
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf("%s\n", str);
}
答案:内存泄漏。
解读:调用malloc()申请内存空间,使用完毕之后没有调用free()释放内存空间并使指针指向NULL。
3.6 请问运行下面的Test()函数会有什么样的后果?
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf("%s\n", str);
}
答案:打印野指针内容,可能是乱码。
解读:GetMemory()返回的是指向栈内存的指针,但该栈内存已被释放,该指针的地址不是 NULL,成为野指针,新内容不可知。
3.7 请问运行下面的Test()函数会有什么样的后果?
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str, "world");
printf("%s\n", str);
}
}
答案:篡改堆区野指针指向的内容,后果难以预料,非常危险。
解读:
(1)free(str);之后,str成为野指针,没有置为NULL,if(str != NULL)语句不能阻止篡改操作。
(2)野指针不是NULL指针,是指向被释放的或者访问受限的内存的指针。
(3)造成野指针原因:①指针变量没有被初始化,任何刚创建的指针不会自动成为NULL;②指针被free或delete之后,没有置NULL;③指针操作超越了变量的作用范围,比如要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
3.8在C语言中memcpy和memmove是一样的吗?
答案:
(1)memcpy()与memmove()一样都是用来拷贝src所指向内存内容前n个字节到dest所指的地址上。
(2)不同的是,当src和dest所指的内存区域重叠时,memcpy可能无法正确处理,而memmove()仍然可以正确处理,不过执行效率上略慢些。
解读:
(1)memcpy()无论什么情况下,都是从前往后拷贝内存。当源地址在前,目的地址在后,且两个区域有重叠时,会造成拷贝错误,达不到理想中的效果。
void *memcpy(void *dest, const void *src, size_t count)
{
if(dest == NULL || src == NULL || count <= 0) return NULL;
char *d = (char *)dest;
char *s = (char *)src;
while(count--)
{
*d++ = *s++;
}
return dest;
}
(2)mem
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
包含241道笔试面试真题详解,还有岗位及校招介绍,简历制作、笔试准备、面试准备的经验分享,以及嵌入式软件工程师技能树解读。你想知道的所有关于嵌入式求职的问题,几乎都可以在这里找到答案。 订阅即赠送学习笔记、简历模板、面试提纲模板、内推机会,需要的同学点击我头像私信即可!