链表的基本操作及链表自身逆序。
/*---- chain operate from Data Structure ---*/
#include
#include
#include
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node *next;
}SLNode;
//---- initiate
void ListInitiate(SLNode **head)
{
if( (*head=(SLNode *)malloc(sizeof(SLNode)))==NULL ) exit(1);
else printf("OK\n");
(*head)->next=NULL;
}
//---- length cal
int ListLength(SLNode *head)
{
SLNode *p=head;
int size=0;
while(p->next!=NULL){
p=p->next;
size++;
}
return size;
}
//----insert a node
int ListInsert(SLNode *head,int i,DataType x)
{
SLNode *p,*q;
int j;
p=head;
j=-1;
while( (p->next!=NULL) && (j
p=p->next;
j++;
}
if(j!=(i-1)) {
printf("Position error\n");
return 0;
}
if((q=(SLNode *)malloc(sizeof(SLNode)))==NULL)
exit(1);
q->data=x;
q->next=p->next;
p->next=q;
return 1;
}
//----delete a node
int ListDelete(SLNode *head,int i,DataType *x)
{
SLNode *p,*s;
int j;
p=head;
j=-1;
while((p->next!=NULL) && (p->next->next!=NULL) && (j
p=p->next;
j++;
}
if(j!=i-1){
printf("Position error\n");
return 0;
}
s=p->next;
*x=s->data;
p->next=p->next->next;
free(s);
return 1;
}
//----- data get
int ListGet(SLNode *head,int i,DataType *x)
{
SLNode *p;
int j;
p=head;
j=-1;
while((p->next!=NULL)&&(j
p=p->next;
j++;
}
if(j!=i) {
printf("Position error\n");
return 0;
}
*x=p->data;
return 1;
}
//----Destroy a chain
void Destroy(SLNode **head)
{
SLNode *p,*p1;
p=*head;
while(p!=NULL) {
p1=p;
p=p->next;
free(p1);
}
*head=NULL;
}
//-----converse a chain
void converse(SLNode *head)
{
SLNode *p,*q;
p=head->next;
head->next=NULL;
while(p!=NULL) {
q=p;
p=p->next;
q->next=head->next;
head->next=q;
}
}
//---- composite operation
int main(void)
{
SLNode *head;
int i,x;
ListInitiate(&head);
for(i=0;i
if(ListInsert(head,i,i)==0){
printf("Error\n");
return 1;
}
}
if(ListDelete(head,0,&x)==0) // chain,position,data address
{
printf("Error\n");
return 1;
}
if(ListInsert(head,0,100)==0) {
printf("Error\n");
return 1;
}
converse(head);
for(i=0;i
if(ListGet(head,i,&x)==0) // chain,position,data address
{
printf("Error\n");
return 1;
}
else printf("%d ",x);
}
printf("\n");
Destroy(&head);
return 0;
}
12
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
形参的内存分配不能实质给实参,函数执行完会销毁。程序会崩溃
GetMemory并不能传递动态内存,
Test函数中的 str一直都是 NULL
()
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
内容未知
可能是乱码
因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
内存泄漏
输出hello
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);之后,str成为野指针,
if(str != NULL)语句不起作用
13
int strcmpa (const char *str1,const char *str2)
{
int len = 0;
assert((str1 != '\0') && (str2 != '\0'));
while(*str1 && *str2 && (*str1==*str2))
{
str1++;
str2++;
}
return *str1-*str2;
}
char *strcpy(char *strDest, const char *strScr)
{
char *address=strDest;
assert((strDest != NULL) && (strScr != NULL));
while(*strScr) //是while(*strScr != ’\0’)的简化形式;
{
*strDest++ = *strScr++;
}
*strDest = '\0'; //当strScr字符串长度小于原strDest字符串长度
return address; //时,如果没有改语句,就会出错了。
}
14
#include"string.h"
main()
{
char*src="hello,world";
char* dest=NULL;
int len=strlen(src);
dest=(char*)malloc(len);
char* d=dest;
char* s=src[len];
while(len--!=0)
d++=s--;
printf("%s",dest);
return 0;
}
int main()
{
char* src = "hello,world";
int len = strlen(src);
char* dest = (char*)malloc(len+1);//要为分配一个空间 char* d = dest;
char* s = &src[len-1]; //指向最后一个字符
while( len-- != 0 )
*d++=*s--;
*d = 0; //尾部要加’\0’
printf("%sn",dest);
free(dest); // 使用完,应当释放空间,以免造成内存汇泄露
dest = NULL; //防止产生野指针
return 0;
}
15
用宏定义写出swap(x,y)
答#define swap(x, y)
x = x + y;
y = x - y;
x = x - y;
16
全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量储存在静态数据库,局部变量在堆栈。动态申请的数据放在堆区。
静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。
17
(1)什么是预编译,何时需要预编译:
答案:
1、总是使用不经常改动的大型代码体。
2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。
18
要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
答案:*((void (*)( ))0x100000 ) ( );首先要将0x100000强制转换成函数指针,即: (void (*)())0x100000然后再调用它: *((void (*)())0x100000)();用typedef可以看得更直观些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)();
19
data ---> 可寻址片内ram
bdata ---> 可位寻址的片内ram
idata ---> 可寻址片内ram,允许访问全部内部ram
pdata ---> 分页寻址片外ram (MOVX @R0) (256 BYTE/页)
xdata ---> 可寻址片外ram (64k 地址范围FFFFH)
code ---> 程序存储区 (64k 地址范围),对应MOVC @DPTR
领取专属 10元无门槛券
私享最新 技术干货