1. 关键字Volatile有什么意义,并举出三个例子
告诉编译器volatile 修饰的值是随时可能发生变化的,每次使用它的时候必须从地址中读取,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
另外:
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr) {
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!
正确的代码如下:
long square(volatile int *ptr) {
int a;
a = *ptr;
return a * a;
}
Volatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以避免在其中一个线程操作该变量时,将其拷贝入寄存器。
请看以下情形: A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条件(它期待B线程改变变量的值。
在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。 volatile 就是在此种情况下使用。
2. 嵌入式系统总是要用户变量或寄存器进行位操作。给定一个整变量a,写两段代码,第一个设置a的bit 3,第二个清楚的a的bit 3,在以上两个操作中,要保持其它位不变。
用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
#define BIT3 (0×1<<3)
static int a;
void set_bit3(void)
{ a |= BIT3;
} void clear_bit3(void)
{ a &= ~BIT3;
}
一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
3. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址位0x67a9整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;
4. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。 具代表事实是,产生一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute _area(double radius)
{
double area = PI*radius *radius;
printf(” Area = %f”, area);
return area;
}
这个函数有太多的错误:
1). ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2). ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
3). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
4). 与第三点一脉相承,printf()经常有重入和性能上的问题。
5.请问运行test函数会有什么结果?为什么?
(1)void getmemory( char *p )
{
P=(char*)malloc( 100 );
}
void test( void )
{
Char *str = null;
getmemory(str);
strcpy( str, “hello world” );
Printf( str );
}
(2)char *getmemory( void )
{
char p[] = “hello world”;
return p;
}
void test( void)
{
char *str = null;
str = getmemory();
printf( str );
}
(3)void getmemory( char **p, int num )
{
*p =(char*)malloc( num );
}
Void test( void )
{
Char* str = null;
getmemory( &str, 100 );
Strcpy( str, “hello” );
Printf( str );
}
(1)分配得到 的内存无法返回到主函数中,运行为段错误。
(2)主函数的str没有分配到内存,只有四个字节,传递回来的地址越界,打印为乱码;
(3)打印为hello world
6. 用一句语句实现x是否是2的若干次幂的判断?
#define is2*n(x) ((x & (x - 1))? 0 : 1)
int main(void)
{
int m = 512;
cout << ((m & (m - 1)) ? false : true) << endl;
//即当m中只有一位为1时,才为若干次幂值
//若有两个及以上1,则(m & (m - 1))不为0,输出0,表示不为2的若干次幂
return(0);
}
7. 下面的程序输出的结果是_______?
#include <stdio.h>
int main (void)
{
int a =100;
int b[3]={200,300,400};
Int c=500;
printf(“%d\n”, b[3]);
return 0;
}
结果为:500,
原因:首先保存在内存中的数组b,然后是变量c,最后是变量a,三个变量的地址相连
void main(void)
{
int a[5]={1, 2, 3, 4, 5};
Int *ptr=(int *)(&a+1);
printf(”%d, %d”, *(a+1), *(ptr-1));
}
结果为: 2, 5
原因: (&a + 1)表示整个数组的地址往后+4字节,跟(&a[0] + 1)与(a + 1)是不一样的
9. 写出字符串strcpy的函数实现方程式.char *strcpy(char *dest, const char *src)
{
assert(dest != NULL && src != NULL); //对参数合法性进行判断
char * pdest = dest; //记录目标串的开始位置
while((*pdest++ = *src++) != '\0'); //逐个复制字符
return dest;
}
在写该函数的时候有点最容易被忽略的地方是对指针参数的合法性检查,从而造成函数功能的脆弱。
另一个容易被忽略的地方时src指向的内容在函数中是不能被修改的,因此其传递的参数必须加上const来修饰。
10. 不使用库函数,编写函数 int strcmp(char *source, char *dest)相等返回0, 不等返回-1;
#include <stdlib.h>
int strcmp(char *source, char *dest)
{
while(*source == *dest && *source != '\0' && *dest != '\0')
{
source++;
dest++;
}
if (*source =='\0' && *dest == '\0')
return 0;
else
return -1;
}
int main()
{
char *str1 = "abcde";
char *str2 = "abcde";
printf("ret = %d", mystrcmp(str1, str2));
return 0;
}
11. 写一个标准宏实现两个数之间的交换。(不使用第三个变量)
#include <stdio.h>
#include <stdlib.h>
// 交换两个数据,但是不适用第三个变量
void swap(int* a, int* b)
{
*b = (*a) ^ (*b);
*a = (*a) ^ (*b);
*b = (*a) ^ (*b);
}
int main()
{
int a = 3;
int b = 4;
printf("before swap, a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("after swap, a = %d, b = %d\n", a, b);
return 0;
}
12. 一个链表的接点结构
Struct Node
{
int data;
Node *next;
};
typedef struct Node Node ;
已知链表的头接点head,写一个函数把这个链表逆序。
参考:http://blog.youkuaiyun.com/hapiman11/article/details/8659144