英文:
Measuring the execution time of a function call in C using a function-like macro
问题
以下是您要翻译的内容:
使用标准库函数 clock()
是在 C 中测量函数调用执行时间的几种方法之一。例如,可以如下比较两个函数(具有不同原型)的执行时间:
#include <stdio.h>
#include <time.h>
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1, b, a+b); }
int main(void) {
double start, elapsed1, elapsed2;
printf("n f g\n");
for(int n = 30; n <= 40; n++) {
start = (double) clock();
f(n);
elapsed1 = (clock() - start) / CLOCKS_PER_SEC;
start = (double) clock();
g(n, 1, 1);
elapsed2 = ((double) clock() - start) / CLOCKS_PER_SEC;
printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
}
return 0;
}
为了使这段代码更加简洁,我们可以定义一个类似函数的宏(因为在 C 中没有“通用函数”指针):
#include <stdio.h>
#include <time.h>
double START, ELAPSED;
#define CPUTIME(FCALL) (START = (double) clock(), FCALL, ELAPSED = ((double) clock() - START) / CLOCKS_PER_SEC)
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1,b,a+b); }
int main(void) {
printf("n f g\n");
for(int n = 30; n <= 40; n++)
printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
return 0;
}
问题: 是否有办法使变量 START 和 ELAPSED 局部于宏定义,以便宏仍然可以作为非 void “函数”调用?是否有更好的方法使代码更简洁,而不使用宏定义?
英文:
Using the standard library function clock()
is one of several methods to measure the execution time of a function call in C. So, for example, the comparison of the execution times of two functions (with different prototypes) can be done as follows:
#include <stdio.h>
#include <time.h>
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1, b, a+b); }
int main(void) {
double start, elapsed1, elapsed2;
printf("n f g\n");
for(int n = 30; n <= 40; n++) {
start = (double) clock();
f(n);
elapsed1 = (clock() - start) / CLOCKS_PER_SEC;
start = (double) clock();
g(n, 1, 1);
elapsed2 = ((double) clock() - start) / CLOCKS_PER_SEC;
printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
}
return 0;
}
To make this code more concise, we could define a function-like macro (since there is no "generic function" pointer in C):
#include <stdio.h>
#include <time.h>
double START, ELAPSED;
#define CPUTIME(FCALL) (START = (double) clock(), FCALL, ELAPSED = ((double) clock() - START) / CLOCKS_PER_SEC)
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1,b,a+b); }
int main(void) {
printf("n f g\n");
for(int n = 30; n <= 40; n++)
printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
return 0;
}
Questions: Is there a way to make variables START and ELAPSED local to the macro definition so that the macro can still be called as a non-void "function"? Is there a better way to make the code more concise, without using a macro definition?
答案1
得分: 2
你可以使用非标准的 statement-expression C 扩展(至少在 clang、gcc 和 tinycc 中可用)。
#include <stdio.h>
#include <time.h>
#define CPUTIME(FCALL) ({ double START = clock(); FCALL; ((double) clock() - START) / CLOCKS_PER_SEC; })
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1, b, a+b); }
int main(void) {
printf("n f g\n");
for(int n = 30; n <= 40; n++)
printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
return 0;
}
这是一个括号包围的块,它被评估为其中的最后一个语句所评估的结果。
我认为在标准 C 中没有通用的解决方案能够满足您的 API 约束。如果您追求标准 C 的线程安全性和/或稍微更好的代码生成,您可以使用您的原始解决方案,并在调用宏的块内(重新)声明变量。
英文:
You can use the nonstandard statement-expression C extension
(available in at least clang, gcc, and tinycc).
#include <stdio.h>
#include <time.h>
#define CPUTIME(FCALL) ({ double START = clock(); FCALL; ((double) clock() - START) / CLOCKS_PER_SEC; })
int f(int n) { return n < 3 ? 1 : f(n-1) + f(n-2); }
int g(int n, int a, int b) { return n < 3 ? b : g(n-1,b,a+b); }
int main(void) {
printf("n f g\n");
for(int n = 30; n <= 40; n++)
printf("%d %.1f %.1f\n", n, CPUTIME(f(n)), CPUTIME(g(n, 1, 1)) );
return 0;
}
It's a parenthesized block that's evaluated to what the last statement in it evaluates to.
I don't think there's a generic solution within standard C that would satisfy your API constraints. If you're after standard-c-only threadsafety and/or slightly better codegen, you could use your original solution and (re)declare the variable(s) locally within the block that calls the macro.
答案2
得分: 1
以下是翻译好的内容:
"在不使用宏定义的情况下,有没有更简洁的方法来编写代码呢?
虽然宏定义很巧妙,但普通的函数可以减少重复,并且更容易理解:
double seconds_since(clock_t start)
{
return (double)(clock() - start) / CLOCKS_PER_SEC;
}
int main(void) {
clock_t start;
double elapsed1, elapsed2;
printf("n f g\n");
for(int n = 30; n <= 40; n++) {
start = clock();
f(n);
elapsed1 = seconds_since(start);
start = clock();
g(n, 1, 1);
elapsed2 = seconds_since(start);
printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
}
return 0;
}
```"
<details>
<summary>英文:</summary>
> Is there a better way to make the code more concise, without using a macro definition?
While the macro definition is clever, just a plain function can reduce the repetition and is simple to understand:
double seconds_since(clock_t start)
{
return (double)(clock() - start) / CLOCKS_PER_SEC;
}
int main(void) {
clock_t start;
double elapsed1, elapsed2;
printf("n f g\n");
for(int n = 30; n <= 40; n++) {
start = clock();
f(n);
elapsed1 = seconds_since(start);
start = clock();
g(n, 1, 1);
elapsed2 = seconds_since(start);
printf("%d %.1f %.1f\n", n, elapsed1, elapsed2);
}
return 0;
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论