输入15名学生的C语言成绩,统计输出该课程的平均成绩,最高成绩和最低成绩并统计输出及格同学的个数。
上代码:
#include <stdio.h>
int main() {
int scores[15];
int sum = 0;
int max = 0;
int min = 100;
int passed = 0;
for (int i = 0; i < 15; i++) {
printf("请输入第 %d 名学生的成绩:", i+1);
scanf("%d", &scores[i]);
sum += scores[i];
if (scores[i] > max) {
max = scores[i];
}
if (scores[i] < min) {
min = scores[i];
}
if (scores[i] >= 60) {
passed++;
}
}
float average = (float)sum / 15;
printf("平均成绩是 %.2f\n", average);
printf("最高成绩是 %d\n", max);
printf("最低成绩是 %d\n", min);
printf("及格同学的个数是 %d\n", passed);
return 0;
}
register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
——百度百科
我用原文的示例代码来编译运行,发现优化后的函数并没有运行得更快,这可能与数组太大存在一定关系(但是数组太小,运行时间直接变 0 us),也有可能是 register 修饰符自身的问题(见下文引用部分)。
#define LEN (1024 * 1024 * 64)
int array[LEN];
#if 1 // 优化前的函数
void foo(int* dest)
{
*dest = 0;
for(int i = 0; i < LEN; i++)
{
*dest = *dest + array[i];
}
}
#else // 使用 register 修饰符优化频繁读写的变量
void foo(int* dest)
{
register int tmp = 0;
for(int i = 0; i < LEN; i++)
{
tmp = tmp + array[i];
}
*dest = tmp;
}
#endif
但是使用register修饰符有几点限制。
首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。
其次,因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。
由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。
在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。
早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定哪些变量应该被存到寄存器中时,C编译环境能比程序员做出更好的决定。实际上,许多编译程序都会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令。——百度百科
附录
技巧1对应测试代码
#include <stdio.h>
#include <sys/time.h> //struct timeval
#include <unistd.h>
#define M 10240 // 二维数组行数
#define N 1024 // 二维数组列数
int array[M][N]; // 大数组需要声明为全局变量
#define ROW_MAJOR 0 // 是否开启行优先
int sum(int a[M][N])
{
int i, j, sum = 0;
#if ROW_MAJOR // 先遍历行,再遍历列
for (i = 0; i < M; ++i)
for (j = 0; j < N; ++j)
sum += a[i][j];
#else // 先遍历列,再遍历行
for (j = 0; j < N; ++j)
for (i = 0; i < M; ++i)
sum += a[i][j];
#endif
return sum;
}
int main()
{
struct timeval tv_start, tv_end;
long int duration = 0; //运行时长
int i = 0, j = 0;
// 数组初始化(随意)
for(i = 0; i < M; i++)
for(j = 0; j < N; j++)
array[i][j] = i % 10;
printf("数组初始化完成,开始运行 sum 函数\r\n");
gettimeofday(&tv_start,NULL); //获取1970-1-1到现在的时间保存到timeval变量
// 要测试的代码
int ret = sum(array);
gettimeofday(&tv_end,NULL);
// printf("函数运行结果:%d\r\n", ret);
if(tv_end.tv_sec == tv_start.tv_sec)
duration = tv_end.tv_usec - tv_start.tv_usec;
else
duration = tv_end.tv_usec + 1000000 - tv_start.tv_usec;
// printf("start=%ld,end=%ld\r\n", tv_start.tv_usec, tv_end.tv_usec);
printf("数组方法方式:%s\n", ROW_MAJOR ? "行优先" : "列优先");
printf("程序运行时长:%ld us\n", duration);
return 0;
}