1、int a=3, *p=&a;
*p的值是()
A、变量a的地址值
B、无意义
C、变量p的地址值
D、3
答:应该选D。
题干可以分解为:
int a=3;
int *p;
p=&a;
所以p存放的是a的地址,所以*p==a,即为3。
************************************************************************************************************************************************
2、int i=1;
void main()
{
int i=i;
puts(i);
}
问打印结果是什么?
答:用事实说话吧
1
2
3
4
5
6
7
|
int i=1; void main() { int i=i; printf ( "%d
" ,i); //使用这个打印为乱码 //puts(i); 使用这句有错误 } |
事实证明i的值为一个未初始化的乱码,虽然有个全局变量i,但main()函数中的局部变量i把全局的i覆盖了,然后又用未初始化的i赋给它自己,所以仍然是个未初始化的变量。事实证明,在编译程序时,系统会给出警告,说i没有被初始化。
************************************************************************************************************************************************
3、void main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a+1);
printf("%d,%d
",*(a+2),*(ptr-2));
}
答:经过试验,发现输出是3,4,3我理解,4不理解,上网搜索解释。
分析:不要混淆&a、&a[0]、a。这三者中,a是数组首地址,即a=&a[0],注意&a是数组指针,所以&a+1不是简单的首地址+1,而是“首地址+一个数组a大小偏移”,所以ptr指针指向的是数组的最末尾,原数组是a[0]、a[1]、a[2]、a[3]、a[4],不妨理解为ptr指向的a[5],当然实际上没有这个,这是为了便于理解,因此ptr-1指向a[4],ptr-2指向a[3],*(ptr-2) = 4。
************************************************************************************************************************************************
4、判断最后的输出值是什么?
int f(int i) {return ++i;}
int g(int i) {return ++i;}
int h(int i) {return ++i;}
void main()
{
int a=0,b=0,c=0;
a += f(g(a));
b += g(g(b));
c += f(h(b));
printf("%d,%d,%d ",a,b,c);
}
答:2,2,4。
注意在各子函数中,++i的i是各子函数局部变量,不会影响main函数中的实参。
************************************************************************************************************************************************
5、写一个宏,将32位无符号数x循环左移n位。
答:#define CircleMove(x,n) ((x)=((x)<<(n)) | ((x)>>(32-n)))
先看网上关于循环移位的函数比较好理解
int CircleMove(int x,int m,int n) //x为要移位的数,m该数的位数(题中要求32位),n为要移动的位数,该函数实现循环左移功能
{
int tmp1 = x >> (m-n);
int tmp2 = x << n;
x = tmp1 | tmp2;
return x;
}
然后根据这个函数写宏定义就好写一点
#define CircleMove(x,n) ((x)=((x)<<(n)) | ((x)>>(32-n)))
************************************************************************************************************************************************
6、构造函数没有返回值,如何处理构造函数中可能发生的错误?
答:抛出异常
************************************************************************************************************************************************
7、给定一个单向链表,设计函数找出该链表中倒数第m个元素,其中m>0,如果m=1,则返回最后一个元素(尾元素),链表元素定义如下:
typedef struct Link{
void *data;
struct Link* next;
} LINK, *PLINK;
需要解答者补充的函数原型为 PLINK FindReverse(PLINK pHead, int m);
答:
PLINK FindReverse(PLINK pHead, int m)
{
if (pHead == NULL)
return NULL;
//遍历链表,确定链表元素总数
PLINK pCurrent = pHead;
unsigned int Count = 0; //pCurrent指向NULL时,Count还要再自加一次才退出循环,所以此处应赋零,最终数才是总数
while(pCurrent != NULL)
{
pCurrent = pCurrent->next;
Count++;
}
//如果元素总数少于m个,函数结束
if(Count < m) return NULL;
//倒数第m个元素就是正数第(总数-m)个元素
pCurrent = pHead;
for(int i=0; i<Count-m; i++)
{
pCurrent = pCurrent->next;
}
return pCurrent;
}
参考:http://blog.csdn.net/asce1885/article/details/5618278
************************************************************************************************************************************************
8、已知一个单向链表,写一个函数,将其顺序反转,链表元素定义如下:
struct node{
void *data;
struct node *pNext;
} Node;
答:参考文章 http://blog.csdn.net/beiyetengqing/article/details/7596554
struct node* LinkReverse(struct node * pHead)
{
struct node * Pre;
struct node * NextCopy;
struct node * Current;
Current = pHead;
while(Current != NULL)
{
NextCopy = Current.pNext; //在更改pNext之前备份它,以便对当前节点操作完后寻找下一个节点并将下个节点作为操作节点
Current.pNext = Pre; //让节点的pNext指向Pre,Pre指向上一个节点
Pre = Current; //更新Pre指向当前这个节点,当前这个节点到下一个节点作为操作节点时,其身份就变成了“上一个节点”。
Current = NextCopy;//更新Current,利用备份的更改前的Current.pNext找到下个节点,并将下个节点作为操作节点。
}
}
上面的方法是非递归方法,这个题还有一个递归的方法:参考:http://blog.csdn.net/beiyetengqing/article/details/7596554
struct node * NextCopy, *reverseNode;
struct node * LinkReverse(struct node * Current)
{
NextCopy = Current.pNext;
Current.pNext = NULL;
reverseNode = LinkReverse(NextCopy);//从程序开头到这一句递归,程序将所有节点的pNext保存,帮将原节点的pNext清空,并且程序游标到达最后一个节点,reverseNode保存的就是最后一个节点,也是反转后的链表的头节点。
NextCopy.pNext = Current;//这一步通过递归的作用完成反转
return reverseNode;
}