c - 在C中通过引用定义数组元素
问题描述
我正在重写一个迭代二维数组的函数(它有效,所以我显然很想打破它)。该函数将为给定键的内容读取 INI 文件,并将返回的值存储到变量或将默认值存储到变量(在我的结构中,变量通过引用定义为 *pStoreToRef)。
支持在我的二维数组中存储默认值被证明是困难的。必须适应所有数据类型。怎么做?
二维数组由以下结构类型化:
typedef struct s_defaults {
char *cKeyTitle;
uint16_t nItemNr;
uint8_t nVarType;
int *pDefaultValue;
uint16_t nVarLength;
uint8_t nVarFloatDecimals;
char *pFormatString;
int *pStoreToRef;
int nNextItem; // set to -1 at end
} site_defaults_t;
这是初始化程序:
site_defaults_t site_defaults[] =
{
{"AUTOTUN_TOTAL_CYCLES\0", SD_AUTORUN_TOTAL_CYCLES, VT_INTEGER, 192, 5, 0, "%i\0", (int*)&aAutoRunControl.nTotalCycles,1},
{"AUTORUN_TEST_INTERVAL\0", SD_AUTORUN_TEST_INTERVAL, VT_INTEGER, 60, 5, 0, "%i\0", (int*)&aAutoRunControl.nTestIntervalSecs,2},
{"AUTORUN_TEST_LEN_SECS\0", SD_AUTORUN_TEST_LEN_SECS, VT_INTEGER, 30, 6, 0, "%i\0", (int*)&aAutoRunControl.nTestLengthSecs,3},
{"AUTORUN_TEST_FAN_SPEED\0", SD_AUTORUN_TEST_FAN_SPEED, VT_INTEGER, 85, 3, 0, "%i\0", (int*)&aAutoRunControl.nSpeed,4},
{"AUTORUN_TEST_PLATE_VOLTS\0", SD_AUTORUN_TEST_PLATE_VOLTS, VT_FLOAT, 40, 3, 1, "%2.1f\0", (int*)&aAutoRunControl.vPlate,5},
{"AUTORUN_TEST_SAMPLES_PER_SEC\0", SD_AUTORUN_TEST_SAMPLES_PER_SEC, VT_INTEGER, 10, 2, 0, "%i\0", (int*)&aAutoRunControl.nSamplesPerSecond,6},
{"SEND_FILES_FREQUENCY\0", SD_SEND_FILES_FREQUENCY, VT_INTEGER, 10, 6, 0, "%i\0", (int*)&oSystemInfo.nSendFilesFrequency,7},
{"POWER_60_HZ\0", SD_POWER_60_HZ, VT_BOOLEAN, true, 1, 0, "%i\0", (int*)&aSystemState.Power60Hz,8},
{"UPLOAD_ON_BOOT\0", SD_UPLOAD_ON_BOOT, VT_BOOLEAN, false, 1, 0, "%i\0", (int*)&oSystemInfo.EnableSendFilesOnBoot,9},
{"AUTORUN_SENDFILES\0", SD_AUTORUN_SENDFILES, VT_BOOLEAN, true, 1, 0, "%i\0", (int*)&aAutoRunControl.sendFiles,10},
{"PREAMP_TRIM\0", SD_PREAMP_TRIM, VT_FLOAT, 0, 3, 1, "%2.1f\0", (int*)&aSystemState.nPreampTrim,11},
{"AUTORUN_PCIL_CONVERSION_CONST\0", SD_AUTORUN_PCIL_CONVERSION_CONST, VT_FLOAT, 0.07608, 2, 8, "%2.8f\0", (int*)&aAutoRunControl.pcilMult,12},
{"ENABLE_DVDT_BEEP\0", SD_ENABLE_DVDT_BEEP, VT_BOOLEAN, false, 1, 0, "%i\0", (int*)&oSystemInfo.AllowDvDtBeep,13},
{"AUTORUN_PCIL_CONVERSION_ADJUST\0",SD_AUTORUN_PCIL_CONVERSION_ADJUST, VT_FLOAT, 0.02, 2, 8, "%2.8f\0", (int*)&aAutoRunControl.pcilMultAdjust,14},
{"AUTORUN_DEMO_DURATION\0", SD_AUTORUN_DEMO_DURATION, VT_INTEGER, 30, 5, 0, "%i\0", (int*)&aAutoRunControl.nDemoDuration,-1},
};
新字段,int *pDefaultValue;被证明是有问题的。我的理论是存储对值的引用,并且以这种方式存储的 pDefaultValue 可以是任何类型。如果要存储的默认值可以引用到地址,那应该可以工作,但在这种情况下呢?
关于解决方法的任何想法?
解决方案
这是许多可能的解决方案之一。由于您使用 VARIANT 来描述信息,所以让我们使用 VARIANT。
为了清楚起见,我已经删除了其他结构成员,因为这完全是关于初始化 VARIANT 并且在这种情况下无关紧要。
首先是这个例子的增强结构:
typedef struct SiteMeta {
char* name;
VARIANT v;
};
定义一个函数来初始化一个 VARIANT。
VARIANT VariantValInit(const VARTYPE vt, const void* value) {
VARIANT v;
VariantInit(&v);
v.vt = vt;
switch (vt) {
case VT_I4:
v.intVal = (int)value;
break;
case VT_BOOL:
v.boolVal = (bool)value;
break;
default:
// throw or something.
break;
}
return v;
}
当然,上面的功能需要额外的案例来支持其他类型。
现在像这样声明你的默认值:
SiteMeta site_defaults[] =
{
{ "AUTOTUN_TOTAL_CYCLES", VariantValInit(VT_I4, (void*)192) },
{"POWER_60_HZ", VariantValInit(VT_BOOL, (void*)true) }
};
推荐阅读
- grails - Grails 3 enumType 用于枚举集
- java - 动态添加按钮到片段
- python-3.x - 带有附加选项的 Python3 xdist
- javascript - 使用 Highcharts 和 AngularJs 的实时条形图
- php - 如何在 drupal 视图中添加自定义字段?
- ios - 将 maxlength 设置为特定的 UITextField
- json - 如何在不使用任何外部库的情况下验证 JSON 对象
- javascript - 我的 jquery 日期时间选择器有错误,它改变了我关注控件的时间
- javascript - javascript根据条件从嵌套的对象数组中返回属性值
- android - Android WIFI ADB 插件不适用于某些 Android 真机?