C:如何使用宏找到数组的最大元素
C: How to find the greatest element of array using macros
我有 3 个用 C 语言编写的函数。
int greatest_int(int* arr, int arr_size) {
int g_int = arr[0]; //g_int is short for greatest_integer
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_int)
g_int = arr[i];
return g_int;
}
long greatest_long(long* arr, int arr_size) {
long g_long = arr[0];
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_long)
g_long = arr[i];
return g_long;
}
double greatest_float(double* arr, int arr_size) {
double g_float = arr[0];
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_float)
g_float = arr[i];
return g_float;
}
这三个函数基本上遵循相同的过程。唯一的区别是它们对不同的类型进行操作。我想减少这个重复的代码,并创建一个适用于任何原始类型的通用函数。
我想到的一个想法是使用函数宏。例如,下面的宏适用于任何原始类型。
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
这是我尝试编写的宏。
#define GREATEST(type, arr, size) {\
type g_value = arr[0];\
for (int i = 1; i < (size); i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;\
}
这个宏不代表任何数值,它只是扩展成一堆语句。
如何修复宏,使其扩展到数组的最大值? (或者我的宏观方法一开始就有缺陷?)
每种类型的函数都必须单独声明。您可以使用宏来减少重复:
#include <stddef.h>
#define GREATEST(type) type greatest_##type(type* arr, size_t size) {\
type g_value = arr[0];\
for (size_t i = 1; i < size; i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;\
}
GREATEST(int) // greatest_int
GREATEST(long) // greatest_long
GREATEST(double) // greatest_double
或者,如果您希望更明确,则仅对重复的代码部分使用宏:
#include <stddef.h>
#define GREATEST g_value = arr[0];\
for (size_t i = 1; i < size; i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;
int greatest_int(int *arr, size_t size) { int GREATEST }
long greatest_long(long *arr, size_t size) { long GREATEST }
double greatest_double(double *arr, size_t size) { double GREATEST }
测试代码:
#include <stdio.h>
#define ARR {1,2,5,8,2,9,3,0,2,-5,11,-12}
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
int main() {
int i[] = ARR;
printf("%d\n", greatest_int(i, ARR_SIZE(i)));
long l[] = ARR;
printf("%ld\n", greatest_long(l, ARR_SIZE(l)));
double d[] = ARR;
printf("%f\n", greatest_double(d, ARR_SIZE(d)));
}
使用 C11,您可以将 3 个声明合并到一个宏中,以自动进行类型选择:
#define greatest(arr, size) _Generic(arr,\
int*: greatest_int,\
long*: greatest_long,\
double*: greatest_double\
)(arr, size)
测试代码:
#include <stdio.h>
#define ARR {1,2,5,8,2,9,3,0,2,-5,11,-12}
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
int main() {
int i[] = ARR;
printf("%d\n", greatest(i, ARR_SIZE(i)));
long l[] = ARR;
printf("%ld\n", greatest(l, ARR_SIZE(l)));
double d[] = ARR;
printf("%f\n", greatest(d, ARR_SIZE(d)));
}
如果您有 C11 编译器,请使用 _Generic
(尽管它并没有真正减少重复代码)
#include <stdio.h>
#define GREATEST(a, b) _Generic((a), \
int*: greatest_int, \
long*: greatest_long, \
double*: greatest_float \
)(a, b)
int greatest_int(int* arr, size_t arr_size) {
int g_int = arr[0]; //g_int is short for greatest_integer
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_int) g_int = arr[i];
}
return g_int;
}
long greatest_long(long* arr, size_t arr_size) {
long g_long = arr[0];
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_long) g_long = arr[i];
}
return g_long;
}
double greatest_float(double* arr, size_t arr_size) {
double g_float = arr[0];
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_float) g_float = arr[i];
}
return g_float;
}
int main(void) {
printf("int: %d\n", GREATEST(((int[]){42, -1, 2022, -1000}), 4));
printf("long: %ld\n", GREATEST(((long[]){42, -1, 2022, -1000}), 4));
printf("double: %f\n", GREATEST(((double[]){42, -1, 2022, -1000}), 4));
return 0;
}
使用与 qsort()
相同的机制。您可以将想法扩展到 time_t
、struct whatever
、...
#include <stddef.h>
size_t greatest(void *arr, size_t nel, size_t width, int (*cmp)(void *a, void *b)) {
unsigned char *a = arr;
size_t index = 0;
for (size_t i = 1; i < nel; i++) {
if (cmp(a+i*width, a+index*width) > 0) index = i;
}
return index;
}
#include <stdio.h>
int cmp_int(void *a, void *b) { if (*(int*)a < *(int*)b) return -1; return *(int*)a != *(int*)b; }
int cmp_long(void *a, void *b) { if (*(long*)a < *(long*)b) return -1; return *(long*)a != *(long*)b; }
int cmp_double(void *a, void *b) { if (*(double*)a < *(double*)b) return -1; return *(double*)a != *(double*)b; }
int main(void) {
int ia[] = {42, -1, 2022, -1000};
long la[] = {42, -1, 2022, -1000};
double da[] = {42, -1, 2022, -1000};
printf("int: %d\n", ia[greatest(ia, 4, sizeof *ia, cmp_int)]);
printf("long: %ld\n", la[greatest(la, 4, sizeof *la, cmp_long)]);
printf("double: %f\n", da[greatest(da, 4, sizeof *da, cmp_double)]);
return 0;
}
我有 3 个用 C 语言编写的函数。
int greatest_int(int* arr, int arr_size) {
int g_int = arr[0]; //g_int is short for greatest_integer
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_int)
g_int = arr[i];
return g_int;
}
long greatest_long(long* arr, int arr_size) {
long g_long = arr[0];
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_long)
g_long = arr[i];
return g_long;
}
double greatest_float(double* arr, int arr_size) {
double g_float = arr[0];
for (int i = 1; i < arr_size; i++)
if (arr[i] > g_float)
g_float = arr[i];
return g_float;
}
这三个函数基本上遵循相同的过程。唯一的区别是它们对不同的类型进行操作。我想减少这个重复的代码,并创建一个适用于任何原始类型的通用函数。
我想到的一个想法是使用函数宏。例如,下面的宏适用于任何原始类型。
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
这是我尝试编写的宏。
#define GREATEST(type, arr, size) {\
type g_value = arr[0];\
for (int i = 1; i < (size); i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;\
}
这个宏不代表任何数值,它只是扩展成一堆语句。
如何修复宏,使其扩展到数组的最大值? (或者我的宏观方法一开始就有缺陷?)
每种类型的函数都必须单独声明。您可以使用宏来减少重复:
#include <stddef.h>
#define GREATEST(type) type greatest_##type(type* arr, size_t size) {\
type g_value = arr[0];\
for (size_t i = 1; i < size; i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;\
}
GREATEST(int) // greatest_int
GREATEST(long) // greatest_long
GREATEST(double) // greatest_double
或者,如果您希望更明确,则仅对重复的代码部分使用宏:
#include <stddef.h>
#define GREATEST g_value = arr[0];\
for (size_t i = 1; i < size; i++)\
if (arr[i] > g_value)\
g_value = arr[i];\
return g_value;
int greatest_int(int *arr, size_t size) { int GREATEST }
long greatest_long(long *arr, size_t size) { long GREATEST }
double greatest_double(double *arr, size_t size) { double GREATEST }
测试代码:
#include <stdio.h>
#define ARR {1,2,5,8,2,9,3,0,2,-5,11,-12}
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
int main() {
int i[] = ARR;
printf("%d\n", greatest_int(i, ARR_SIZE(i)));
long l[] = ARR;
printf("%ld\n", greatest_long(l, ARR_SIZE(l)));
double d[] = ARR;
printf("%f\n", greatest_double(d, ARR_SIZE(d)));
}
使用 C11,您可以将 3 个声明合并到一个宏中,以自动进行类型选择:
#define greatest(arr, size) _Generic(arr,\
int*: greatest_int,\
long*: greatest_long,\
double*: greatest_double\
)(arr, size)
测试代码:
#include <stdio.h>
#define ARR {1,2,5,8,2,9,3,0,2,-5,11,-12}
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
int main() {
int i[] = ARR;
printf("%d\n", greatest(i, ARR_SIZE(i)));
long l[] = ARR;
printf("%ld\n", greatest(l, ARR_SIZE(l)));
double d[] = ARR;
printf("%f\n", greatest(d, ARR_SIZE(d)));
}
如果您有 C11 编译器,请使用 _Generic
(尽管它并没有真正减少重复代码)
#include <stdio.h>
#define GREATEST(a, b) _Generic((a), \
int*: greatest_int, \
long*: greatest_long, \
double*: greatest_float \
)(a, b)
int greatest_int(int* arr, size_t arr_size) {
int g_int = arr[0]; //g_int is short for greatest_integer
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_int) g_int = arr[i];
}
return g_int;
}
long greatest_long(long* arr, size_t arr_size) {
long g_long = arr[0];
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_long) g_long = arr[i];
}
return g_long;
}
double greatest_float(double* arr, size_t arr_size) {
double g_float = arr[0];
for (size_t i = 1; i < arr_size; i++) {
if (arr[i] > g_float) g_float = arr[i];
}
return g_float;
}
int main(void) {
printf("int: %d\n", GREATEST(((int[]){42, -1, 2022, -1000}), 4));
printf("long: %ld\n", GREATEST(((long[]){42, -1, 2022, -1000}), 4));
printf("double: %f\n", GREATEST(((double[]){42, -1, 2022, -1000}), 4));
return 0;
}
使用与 qsort()
相同的机制。您可以将想法扩展到 time_t
、struct whatever
、...
#include <stddef.h>
size_t greatest(void *arr, size_t nel, size_t width, int (*cmp)(void *a, void *b)) {
unsigned char *a = arr;
size_t index = 0;
for (size_t i = 1; i < nel; i++) {
if (cmp(a+i*width, a+index*width) > 0) index = i;
}
return index;
}
#include <stdio.h>
int cmp_int(void *a, void *b) { if (*(int*)a < *(int*)b) return -1; return *(int*)a != *(int*)b; }
int cmp_long(void *a, void *b) { if (*(long*)a < *(long*)b) return -1; return *(long*)a != *(long*)b; }
int cmp_double(void *a, void *b) { if (*(double*)a < *(double*)b) return -1; return *(double*)a != *(double*)b; }
int main(void) {
int ia[] = {42, -1, 2022, -1000};
long la[] = {42, -1, 2022, -1000};
double da[] = {42, -1, 2022, -1000};
printf("int: %d\n", ia[greatest(ia, 4, sizeof *ia, cmp_int)]);
printf("long: %ld\n", la[greatest(la, 4, sizeof *la, cmp_long)]);
printf("double: %f\n", da[greatest(da, 4, sizeof *da, cmp_double)]);
return 0;
}