具有这样的结构:
struct _Example {
int a;
int b;
int c;
} Example;
一个函数通过指针获取此struct并输出struct成员的值。我想打印这些值:
Example example;
func(&example);
if(example.a)
printf("%d", example.a);
if(example.b)
printf("%d", example.b);
if(example.c)
printf("%d", example.c);
如何用循环替换那些多个if
条件?
答案 0 :(得分:8)
最好的方法可能是在union
上键入修剪。它允许您使用不同的变量表示形式来使用相同的内存区域,例如,通过为每个struct成员指定单独的名称,同时又可以循环遍历它们。
#include <stdio.h>
typedef union {
struct // anonymous struct, requires standard C compiler
{
int a;
int b;
int c;
};
int array[3];
} Example;
int main (void)
{
Example ex = { .a=1, .b=2, .c=3 };
for(size_t i=0; i<3; i++)
{
printf("%d\n", ex.array[i]);
}
}
如果无法更改结构定义,则第二好的选择是通过字符类型进行某种指针运算。不过,这需要多加注意,这样您才不会最终编写行为定义不当的代码-您需要注意对齐和严格的别名等事情。如果结构因使用不同类型的成员而变得更加复杂,则最好使用字符类型,因为字符类型可以避免别名问题。
假设uint8_t
是字符类型,则:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct
{
int a;
int b;
int c;
};
} Example;
int main (void)
{
Example ex = { .a=1, .b=2, .c=3 };
uint8_t* begin = (uint8_t*)&ex;
uint8_t* end = begin + sizeof ex;
for(uint8_t* i=begin; i!=end; i+=sizeof(int))
{
printf("%d\n", *(int*)i);
}
}
答案 1 :(得分:1)
简短的答案是,您不能轻易做到这一点。结构中的成员被设计为通过名称进行访问,而不是被设计为被索引的数组中的元素。
可以通过偏移量计算地址,但是无论如何您仍然需要了解结构布局,最重要的是,该布局可以通过编译器选项或pragma进行更改。
将类型信息携带到更复杂的运行时环境中的语言,例如C#和Java,允许您在运行时枚举结构成员,但是C只是创建一个未注释的数据blob,您必须在编译时知道 ,因此您也可以显式枚举成员。当然,您可以使用通常的C技巧;可能有一个序列化解决方案,可以从包装在宏中的某些结构定义中生成用于访问结构元素的代码(啊,是的,第一个Google匹配:https://gist.github.com/Rhomboid/8e48620badbb3d9b4c30)。
之所以可以在运行时为数组的元素建立索引,是因为数组的内部布局是完全已知的(例如,定义为不包含填充)。
当然,您可以定义一个结构,该结构包含足够大的并集数组以容纳最大的元素,该元素带有自己的类型和“成员”名称信息,然后用于解释该信息,并使用在运行时进行适当的类型转换和printf
转换字符串。实际上,您将模仿更复杂的运行时环境的某些功能。
答案 2 :(得分:0)
如果您将struct
variable
视为单独的对象,则不可能
但是如果您将它们视为array
,则有可能
例如
struct Example {int member[3];};
int main()
{
struct Example example;
int i;
for (i = 0; i < 3; ++i)
example.member[i] = i;
}