gpt4 book ai didi

c - C 中用于获取/设置数组条目的宏

转载 作者:行者123 更新时间:2023-12-02 21:42:43 25 4
gpt4 key购买 nike

下面的小代码输入一个具有行优先排序和两列的矩阵。据我了解,我包含的宏将允许我以更自然的方式访问数组的条目(从 1 索引开始)。

#define Alocal(i,j) Alocal[ (j-1) + 2*(i-1) ]

void test_function(double* Alocal)
{

double a;
double b;

/* get first and second entries of the array */
a = Alocal(1,1);
b = Alocal(1,2);

}

现在我有两个问题:1) 假设我将一个整数 Ncols 传递到函数中。可以在宏中使用它来获得更通用的定义吗?喜欢

#define Alocal(i,j) Alocal[ (j-1) + Ncols*(i-1) ]

2) 有没有办法定义将数组的特定条目设置为宏中的某个数字?喜欢

double d;

d = 3.4579;

Alocal(2,2) = d;

最佳答案

宏提示

  • 将宏参数(可以是表达式)括在括号中,以避免运算符优先级导致的错误。
  • 不要“隐藏”变量和其他名称
  • 在您的情况下,人们应该更喜欢为数组添加一个额外的参数,以提高代码的表达力和这些宏的可重用性
  • 按照惯例,宏名称应全部大写
  • 要隔离宏表达式(类似于函数“返回”void 的做法),您可以至少将 MY_ARRAY_SET 宏放入 do{ ... }while(0) block 。
  • 如果可能,应该实现常规函数(它们也可以内联)...不易出错、较少修改、类型安全

示例

我没有特别关注你的指数计算,参见Ben's answer

#include <stdlib.h>

#define MY_ARRAY_GET(array,i,j) ( (array)[ ((j)-1) + 2*((i)-1) ] )
#define MY_ARRAY_SET(array,i,j,x) ( (array)[ ((j)-1) + 2*((i)-1) ] = (x) )

void test_function(double* Alocal)
{
double a;
double b;

/* get first and second entries of the array */
a = MY_ARRAY_GET(Alocal, 1, 1);
b = MY_ARRAY_GET(Alocal, 1, 2);

MY_ARRAY_SET(Alocal, 1, 2, 42.0);
}

int main(int argc, char** argv)
{
double array[16] =
{ 1.0, 2.0 }; //Initialize to 1.0,2.0,0.0 ...

test_function(array);

return EXIT_SUCCESS;
}

示例 2

尝试将其他答案和评论中的想法放在一起(VLA 和断言)。免责声明:这是概念证明,而不是我如何编写高效代码。

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

//********************************************************************************
//Utility macros

/**
* @brief Internal macros to retrieve the dynamic size of a VLA dimension 1
* @param vla A pointer to the VLA is need in order to properly deduce its dimensions
* @warning for internal use only
*/
#define INTERNAL_VLA_SIZE_D1(vla) (sizeof((*vla))/sizeof((*vla)[0]))

/**
* @brief Internal macros to retrieve the dynamic size of a VLA dimension 2
* @param vla A pointer to the VLA is need in order to properly deduce its dimensions
* @warning for internal use only
*/
#define INTERNAL_VLA_SIZE_D2(vla) (sizeof((*vla)[0])/sizeof((*vla)[0][0]))

//********************************************************************************
//Debug check helper

int is_valid_index_2D(const size_t nrows, const size_t ncols, const size_t row, const size_t col)
{
return (nrows) && (ncols) && ((size_t) (row) < (size_t) (nrows)) && ((size_t) (col) < (size_t) (ncols));
}

//********************************************************************************
//1 based index loop macros

#define FOR_RANGE(type,var,start,end) \
for(type var = (start);var <= (end);++var)

#define FOR(type,var,count) \
FOR_RANGE(type,var,1,count)

#define MAT_FOREACH_INDEX(rowvar,colvar,mat) \
FOR(size_t,rowvar,INTERNAL_VLA_SIZE_D1(&(mat))) \
FOR(size_t,colvar,INTERNAL_VLA_SIZE_D2(&(mat)))

//********************************************************************************
//Matrix functions
//Note: These functions rely upon compiler warnings or errors regarding incompatible pointer types
// (i.E. for a wrong number of array dimensions)

void mat_set(const size_t nrows, const size_t ncols, double (* const matrix)[nrows][ncols], const size_t row, const size_t col, const double value)
{
assert(is_valid_index_2D(nrows,ncols,row,col));
(*matrix)[row][col] = value;
}

double mat_get(const size_t nrows, const size_t ncols, double (* const matrix)[nrows][ncols], const size_t row, const size_t col)
{
assert(is_valid_index_2D(nrows,ncols,row,col));
return (*matrix)[row][col];
}

void mat_identity(const size_t nrows, const size_t ncols, double (* const matrix)[nrows][ncols], double value)
{
for (int row = 0; row < nrows; ++row)
for (int col = 0; col < ncols; ++col)
(*matrix)[row][col] = row == col ? value : 0.0;
}

void mat_fprintf(FILE* stream, const char* const field_delim, const char* const field_format, const size_t nrows, const size_t ncols, double (* const matrix)[nrows][ncols])
{
for (int row = 0; row < nrows; ++row)
{
for (int col = 0; col < ncols; ++col)
{
if (col)
fputs(field_delim, stream);
fprintf(stream, "%.2f", (*matrix)[row][col]);
}
fprintf(stream, "\n"); //write a line break, the portable way
}
}

//Matrix utility macros, using 1 based indices
#define MAT_SET(mat,row,col,value) \
mat_set(INTERNAL_VLA_SIZE_D1(&(mat)),INTERNAL_VLA_SIZE_D2(&(mat)),(&(mat)),(row)-1,(col)-1,value)

#define MAT_GET(mat,row,col) \
mat_get(INTERNAL_VLA_SIZE_D1(&(mat)),INTERNAL_VLA_SIZE_D2(&(mat)),(&(mat)),(row)-1,(col)-1)

#define MAT_SET_IDENTIY(mat,value) \
mat_identity(INTERNAL_VLA_SIZE_D1(&(mat)),INTERNAL_VLA_SIZE_D2(&(mat)),(&(mat)),value)

#define MAT_FPRINTF(stream,field_delim,field_format,mat) \
mat_fprintf((stream),(field_delim),(field_format),INTERNAL_VLA_SIZE_D1(&(mat)),INTERNAL_VLA_SIZE_D2(&(mat)),(&(mat)))

#define MAT_PRINTF(field_delim,field_format,mat) \
MAT_FPRINTF(stdout,(field_delim),(field_format),(mat))

int main(int argc, char** argv)
{
#ifdef NDEBUG
fprintf(stderr, "assertions disabled\n");
#else
fprintf(stdout, "assertions enabled\n");
#endif

//Note: since below VLA is created on stack, we must be cautious about its size
for (size_t nrows = 1; nrows <= 5; ++nrows)
{
for (size_t ncols = 1; ncols <= 5; ++ncols)
{

//Allocate the matrix on stack
double matrix[nrows][ncols];

//Initialize matrix to identity
MAT_SET_IDENTIY(matrix, 1.0);

puts("****************************************");
//Print the matrix using a wrapped function
MAT_PRINTF(", ", "%.2f", matrix);

puts("****************************************");
//Print the matrix using nested loops with 1 based indices
FOR(size_t,row,nrows)
FOR(size_t,col,ncols)
{
printf("%.2f", MAT_GET(matrix, row, col));
if (col < ncols)
printf(", ");
else
printf("\n");
}

puts("****************************************");
//Print the matrix using a 2D foreach with 1 based indices
MAT_FOREACH_INDEX(row, col, matrix)
{
printf("%.2f", MAT_GET(matrix, row, col));
if (col < ncols)
printf(", ");
else
printf("\n");
}

}
}

return EXIT_SUCCESS;
}

关于c - C 中用于获取/设置数组条目的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20083031/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com