What is the purpose and optimization effects of restrict keyword in C language?
restrict Keyword Basic Concepts:
-
Pointer Aliasing Restriction
cvoid copy(int *restrict dest, const int *restrict src, size_t n) { for (size_t i = 0; i < n; i++) { dest[i] = src[i]; } } // dest and src will not point to overlapping memory regions -
Compiler Optimization
c// Without restrict void add_arrays(int *a, int *b, int *c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } } // With restrict void add_arrays_optimized(int *restrict a, const int *restrict b, const int *restrict c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } }
Usage Scenarios:
-
Memory Copy
cvoid memcpy_custom(void *restrict dest, const void *restrict src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; while (n--) { *d++ = *s++; } } -
Mathematical Operations
cvoid vector_add(double *restrict result, const double *restrict a, const double *restrict b, size_t size) { for (size_t i = 0; i < size; i++) { result[i] = a[i] + b[i]; } } -
String Processing
csize_t strlen_custom(const char *restrict str) { size_t len = 0; while (*str++) len++; return len; }
Optimization Effects:
-
Loop Unrolling
cvoid process(int *restrict data, int n) { // Compiler can safely unroll loops for (int i = 0; i < n; i++) { data[i] *= 2; } } -
Vectorization
cvoid scale_array(double *restrict arr, double factor, int n) { for (int i = 0; i < n; i++) { arr[i] *= factor; } // Compiler can use SIMD instructions } -
Cache Optimization
cvoid matrix_multiply(double *restrict result, const double *restrict a, const double *restrict b, int rows, int cols, int k) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { result[i * cols + j] = 0; for (int p = 0; p < k; p++) { result[i * cols + j] += a[i * k + p] * b[p * cols + j]; } } } }
Important Considerations:
-
Undefined Behavior
cvoid dangerous(int *restrict a, int *restrict b) { *a = 10; *b = 20; // If a and b point to same location, undefined behavior } -
Parameter Passing
cvoid function(int *restrict p) { // p won't create aliases within function } int main() { int x = 10; function(&x); // Safe } -
Structure Pointers
cstruct Point { int x, y; }; void transform(struct Point *restrict p) { p->x *= 2; p->y *= 2; }
Practical Application Examples:
-
Image Processing
cvoid grayscale_image(unsigned char *restrict pixels, int width, int height) { for (int i = 0; i < width * height * 3; i += 3) { unsigned char gray = (pixels[i] + pixels[i+1] + pixels[i+2]) / 3; pixels[i] = pixels[i+1] = pixels[i+2] = gray; } } -
Signal Processing
cvoid apply_filter(double *restrict output, const double *restrict input, const double *restrict kernel, int size, int kernel_size) { for (int i = 0; i < size; i++) { output[i] = 0; for (int j = 0; j < kernel_size; j++) { if (i + j < size) { output[i] += input[i + j] * kernel[j]; } } } } -
Data Compression
cvoid compress_data(const int *restrict input, int *restrict output, int size) { int out_index = 0; int current = input[0]; int count = 1; for (int i = 1; i < size; i++) { if (input[i] == current) { count++; } else { output[out_index++] = current; output[out_index++] = count; current = input[i]; count = 1; } } }
Performance Comparison:
-
Without restrict
cvoid add_slow(int *a, int *b, int *c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } // Compiler must consider pointer overlap } -
With restrict
cvoid add_fast(int *restrict a, const int *restrict b, const int *restrict c, int n) { for (int i = 0; i < n; i++) { a[i] = b[i] + c[i]; } // Compiler can aggressively optimize }