现在的位置: 首页 > 综合 > 正文

一些小练习

2013年09月05日 ⁄ 综合 ⁄ 共 4355字 ⁄ 字号 评论关闭

1.
指针参数

void f(char *p)

{

    p=(char *)malloc(10);

}

int
main()

{

char *p=NULL;

f(p);

free(p);

return
0;

}

free(NULL)是可以的,只是指针变量做函数参数仍然是单向的值传递,p指针仍然是0,所以这里内存泄露了。

2.字符数组

char s1[24]="how are u";

char s2[24]="how are you";

int i,len = strlen(s2);

for (i=0;i<len;i++)

  s1[i]=s2[i];

printf("s1=%s s2=%s/n",s1,s2);

这里s1和s2都能正常显示,因为s1后面全是自动补0.

3.void指针转换

class A

{

public:

    A():a(2),p((void *)5)

    {

        printf("a=%d p=%d/n",a,p);

    }

    int a;

    void *p;

};

int main()

{

    A b;

}

这里p一定要用(void *)强制转换,但p的值是5,引用它会造成系统受影响。

4.堆内存,数据段,代码段

#include <stdio.h>
char *f1()
{
char a[]="Hello,
world!!";
return a;
}

char *f2()
{
char *a="Hello,
world!!";
return a;
}
char *f3()
{
      static char *a="Hello, world!";
      return a;
}
void main()
{
char *s1;
char *s2;
char *s3;
s1=f1();
s2=f2();
s3=f3();
puts(s1);
puts(s2);
puts(s3);
}
一个程序在内存中,按照内存地址从低到高的顺序,分布着代码段、常量段、数据段、
堆内存和
栈内存

 

代码段

用来存放程序的机器码

常量段

用来存放所有的字符串常量

数据段

用来存放全局变量和静态变量(这个段在程序加载后自动清0,这就是为什么全局变量和静态变量的初始值都是0)

代码段、常
量段和数
据段内存都是和程序的生命周期相同的,只有程序结束后,该内存才会被释放。数据段又分为已初始化数据段

未初始化数据段


未初始化数据段不影响目标文件的大小。

堆内存

,程序中用malloc等内存分函数申请的内存块,从数据段顶端开始,从低地址向高地址分配。必须调用free等内存释放函数,将不使用的内存释放。

栈内存

,存放函数内的临时变量,程序每进入一个函数前,从栈内存内分配一块内存,大小等于该函数内的临时变量的大小,当函数结束后,该内存被自动释放。栈内存从
高地址向低地址方向分配。

堆内存和栈
内存在被
分配出去后是不会重新初始化的,所以分配的时候内存中放的什么数据,你得到的内存中就是什么数据。这就是为什么临时变量和malloc的内出中的数据是随
机值
的原因。

下面我们来看看前面提到的几种情况:
1). char a[] =
"

Hello,world!";

a是局部字符数组变量,数组大小为13,数组内的元素被初始化为"Hello,world!/0

"。

a被存储在函数f1的栈内存中,return
a将a的首地址返回回去了。f1函数结束后,f1的栈内存被释放,原来a所在的内存地址可能被挪做它用,所以那个地址里面放的是什么东西不得而知,因此
puts输出该地址中的内容得到的结果是随机的。
2

).
char *a =



"

Hello,world!";

a是一个char*指针变量,大小为4个字节,其值是"

Hello,world!"这个常量字符串的首地址。

"

Hello,world!"常量字符串被保存在常量段,不能被更改。

a被存储在函数f1的栈内存中,return
a返回的是指针a的值,即

"

Hello,world!"常量字符串的首地址。f1函数结束后,a被释放了,但a
指向的常量段的内容没有变。因此puts输出是正确的。

3

). static char a[] =
"

Hello,world!";

a是静态字符数组变量,数组大小为13,数组内的元素被初始化为"Hello,world!/0

"。

a被存储在数据段内,return
a将a的首地址返回回去了。f1函数结束后,a所在的内存不会被释放,因此puts输出该地址中的内容得到的就是a中存储的字符串。

5.单链表反转

struct tagT

{

  
int data;

  
struct tagT *next;

};

typedef struct tagT T;

T *revert(T *head)

{

  
T *p=head, *pnext=NULL, *newHead=NULL;

  while(p!=NULL)

 
{

     
pnext=p->next;

     
p->next=newHead;

     
newHead=p;

     
p=pnext;

  }

  return newHead;

}

T *insert(T *head, int data)

{

   
T *newNode = (T *)malloc(sizeof(T));

   
memset(newNode,0,sizeof(T));

   
newNode->data = data;

   
newNode->next = NULL;

    T *p=head;

   
if ( NULL == p )

   
{

         
/* no one node */

         
return newNode;

   
}

   
else

   
{

       
/* point to end */

       
while ( p->next!=NULL )

      
{

         
p=p->next;

       
}

       
/* insert */

       
p->next = newNode;

       
return head;

    
}

}

void print(T *head)

{

    
T *p=head;

    
while (p!=NULL)

   
{

       
printf("%2d ", p->data);

       
p=p->next;

   
}

   
printf("/n");

}

int main()

{

   
T *head = NULL;

   
head = insert(head,1);

   
head = insert(head,2);

   
head = insert(head,3);

   
print(head);

    head = revert(head);

   
print(head);

    return 0;

}

6.两个大数相乘

char *multi(char *a, char
*b)
{
    int n=strlen(a), m=strlen(b);
    int i=0,j=0;
    int temp=0;
    int *c=(int *)malloc(sizeof(int)*(n+m));
    memset(c,0,(n+m)*4);

    for ( i=0;i<n;i++)
        for (j=0;j<m;j++)
            c[i+j+1]+=(a[i]-'0')*(b[j]-'0');

    for ( i=n+m-1;i>=0;i--)
    {
        if ( c[i]>=10 )
        {
            c[i-1]+=c[i]/10;
            c[i]=c[i]%10;
        }
    }

    char *p, *result=(char *)malloc(n+m+1);
    memset(result,0,

n+m+1

);
    i=0;
    while (c[i]==0)
        i++;
    p=result;
    for (;i<n+m;i++,p++)
        (*p)=(c[i]+'0');
    return result;


}

7.用预处理指令

#define
声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

8.写一个“标准”宏MIN

这个宏
输入两个参数并返回较小的一个。

#define MIN(A,B) ((A) <= (B) ?(A) : (B))

再看下面一个例子,输出是多少呢

    #define MAX(A,B) ((A) >= (B)?(A):(B))

    int b=3,a=4;

    int *p=&a;

    int least = MAX((*p)++,b);

    printf("least=%d a=%d b=%d/n", least,a,b);

这个结果是,5,6,3,这就是宏定义的副作用,三目运算符可以看成2个表达式,前面一个已经

把a加1了,然后赋值给least。另外,这里*p++表达式,++的级别要高于*,所以要加括号。

9.

关键字volatile有什么含意

并给出三个不同的例子。

的变量是说这变量可能会被意想不到地改变,

下面是volatile变量的几个例
子:

1). 并行设备的硬件寄存器(如:状态寄存器)

2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic
variables)

3). 多线程应用中被几个任务共享的变量

int
square(volatile int *ptr)

{

return *ptr * *ptr;

}

编译器将产生类似下面的代码:

int
square(volatile int *ptr)

{

int a,b;

a = *ptr;

b = *ptr;

return
a * b;

}

应该为

long
square(volatile int *ptr)

{

int a;

a = *ptr;

return a * a;

}

10.

位操作

写两段代码,第一个设置a的bit
3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

#define BIT3
(0x1<<3)

a |= BIT3;

a &= ~BIT3;

11.

指针地址

要求设置一绝对地址为0x67a9的整
型变量的值为0xaa66

一个整型数

转化成

一指针需要强制转换

short *ptr;

ptr =
(

short

*)0x67a9;

*ptr = 0xaa55;

12 .
类型提升

下面的代码输出是什么,为什么?

void foo(void)

{

     unsigned int a = 6;

    
int b = -20;

     (a+b > 6) puts("> 6") : puts("<= 6");

}

当表达式中存在有符号类型和无符号类型
时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6

13. 评价下面的代码片断

unsigned int zero = 0;

unsigned int compzero = 0xFFFF;

/*1's
complement of zero */

对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

unsigned int compzero = ~0;

抱歉!评论已关闭.