C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
130: Getting the Current Time
I've seen this happen in a dozen code reviews: a developer wants to measure how long a specific function takes to run, so they grab time() from <time.h>, call it before the function, call it after, and subtract the two. On the surface, it looks logically sound. You're getting a timestamp, doing some subtraction, and you have a duration. The problem is that time() returns the current calendar time in seconds. In the world of software engineering, a second is an eternity.
The Second-by-Second Trap
If you're writing a program to log when a user logged in, time() is perfectly fine. But if you're trying to optimize a piece of logic—say, a bubble sort on a small array—your function is likely finishing in a few milliseconds. When you use time(), you'll almost always see a result of 0 seconds, or occasionally 1 second if you happened to call the function exactly as the system clock ticked over to the next second. It's far too coarse to be useful for performance tuning.
// The naive way: useless for performance measurement
time_t start = time(NULL);
do_expensive_calculation();
time_t end = time(NULL);
printf("Elapsed: %ld seconds\n", (long)(end - start)); // Usually prints 0
Measuring with CPU Cycles
When I need to know how much "work" the processor is actually doing, I reach for clock(). Instead of looking at the wall clock on the office wall, clock() looks at the number of clock ticks elapsed since the program started. This gives us a much finer resolution. The return type is clock_t, and to turn that into something human-readable, you divide it by the constant CLOCKS_PER_SEC.
This is the standard way to handle internal profiling in C. It doesn't care about the date or the time of day; it only cares about how many cycles the CPU spent executing your code.
// The better way for profiling
clock_t start = clock();
do_expensive_calculation();
clock_t end = clock();
double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("CPU time used: %f seconds\n", cpu_time_used);
When CPU Time Isn't Wall Time
Here is where it gets tricky, and this is the part that usually trips people up during debugging. clock() measures CPU time, not wall-clock time. If your function calls sleep() or spends a long time waiting for a network packet to arrive, the CPU isn't "working"—it's idling. Consequently, clock() won't tick during that wait.
If you measure a function that sleeps for two seconds, clock() might tell you it only took 0.001 seconds of CPU time. If your goal is to measure the user's actual experience of waiting, clock() is the wrong tool. For that, you'd need platform-specific APIs like clock_gettime on POSIX systems or QueryPerformanceCounter on Windows. But for the vast majority of algorithmic optimization in C, clock() is your best friend because it filters out the noise of the OS scheduler and tells you exactly how hard your code is hitting the processor.
📋 Practical Task
Profiling a Prime Number Search
Write a program that calculates the sum of all prime numbers between 1 and 10,000. You must use clock() to measure exactly how much CPU time the calculation takes.
- Implement a simple
isPrime(int n)helper function. - Capture the starting clock ticks before the loop and the ending ticks after.
- Print the final sum and the elapsed CPU time formatted to four decimal places.
- Experiment: Add a
sleep(1)call inside your loop and observe how theclock()measurement differs from the actual time you spent waiting for the program to finish.
There are no comments for now.