结构数组 - 被覆盖的元素
Struct Arrays - elements being overwritten
首先 - 我对 C 非常生疏......但是有一个项目仍然需要我生疏的技能......对于我可能编码我的解决方案的“粗略”方式表示歉意。
我的基本要求是用稍后要读取和处理的元素简单地填充一个固定的 strut 数组。该数组旨在成为“全局”数组,并从解决方案中的几个 .C 文件中使用。
我遇到的问题是,虽然有些元素添加得很好,但有些元素会被其他元素“覆盖”- 导致数组不准确,因为它不包含所有需要的填充元素。
该结构在头文件中定义为:-
typedef struct {
char* field;
char* value;} Telemetry;
数组初始化如下:-
Telemetry* myArray[5];
要添加到数组,我有一个函数可以检查下一个空“插槽”:-
int addToArray(Telemetry* telemetry)
{
counter = 0;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
break;
}
else
{
Counter++;
}
myArray[counter] = telemetry;
}
}
然后添加元素,应用程序从 CANBUS 系统接收数据 - 并解释每个值:-
//Define Struct Values
//Dialectric
char* dialectricvalueBuffer = (char*)malloc(30);
sprintf(dialectricvalueBuffer, "%f", 50.3);
Telemetry dialectricTelemetry = { .field = "DialectricConst", .value = dialectricvalueBuffer };
//Density
char* densityvalueBuffer = (char*)malloc(30);
sprintf(densityvalueBuffer, "%f", 9);
Telemetry densityTelemetry = { .field = "Density", .value = densityvalueBuffer };
//Viscosity
char* viscosityvalueBuffer = (char*)malloc(30);
sprintf(viscosityvalueBuffer, "%f", 21.9);
Telemetry viscosityTelemetry = { .field = "Viscosity", .value = viscosityvalueBuffer};
//Add values to array
addToArray(&densityTelemetry);
addToArray(&viscosityTelemetry);
addToArray(&dialectricTelemetry);
此时 myArray 的元素 0、1、2 已经填充好了。
然后一个单独的进程(读取温度)执行相同的函数以将元素添加到数组中:-
char* tempvalueBuffer = (char*)malloc(30);
sprintf(tempvalueBuffer, "%f", temperature);
Telemetry tempTelemetry = { .field = "Temperature", .value = tempvalueBuffer };
//Add values to array
addTelemetryToQueue(&tempTelemetry);
并且每一次 - 元素 2 (DialectricConst) 都会被温度元素替换。
无论我将 DialectricConst 元素移动到数组中的何处 - 它总是会尽快被温度数据替换
Telemetry tempTelemetry = { .field = "Temperature", .value = tempvalueBuffer };
执行。
任何关于原因的解释 - 将不胜感激!
有一些细节你没有显示,我必须填写一些假设:
假设...
你有一个从 CANbus 接收的函数和一些其他测量温度的函数。
你提到这些在不同的进程中,但我假设你实际上是指不同的线程或只是其他功能。否则,他们将无法在不付出额外努力的情况下共享同一个数组。
在这两个函数中,您都在堆栈上分配了局部变量。然后将它们添加到您的数组中,您只在数组中存储变量的地址但不分配额外的内存。
这意味着离开这两个函数后,局部变量不再有效。通过数组中的指针访问它们会导致未定义的行为。
假设结束
另一方面,您确实展示了添加元素的功能。
在那个函数中你有一个严重的缺陷:
int addToArray(Telemetry* telemetry)
{
counter = 0;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
break;
}
else
{
Counter++;
}
myArray[counter] = telemetry;
}
}
如果有几个元素已经拥有一个地址,则将新地址存储在每个后继者中
如果 myArray[0] != NULL
你执行 counter++;
然后 myArray[counter] = telemetry;
用有效地址填充 myArray[1]
并且在你循环的下一次迭代中你将再次执行相同的操作直到所有元素都被填充具有相同的值。
另一方面,如果您点击了一个仍然是 NULL
的条目,您将退出循环并且根本不分配任何内容。
这反过来又得出结论,您的声明“此时 myArray 的元素 0、1、2 填充得很好。”远非如此。
最后,你没有return一个值,而你承诺return一个int
。更不用说您没有为 counter
定义类型并且与 Counter
.
大小写不匹配
那么你的调用函数中有更多未定义的行为:
sprintf(densityvalueBuffer, "%f", 9);
这传递了一个 int
值,而你承诺传递一个 double
值。
您的编译器在遇到该代码时应该会显示一些警告。
固定版本为:
int addToArray(Telemetry* telemetry)
{
Telemetry *new_elem = malloc(sizeof(*new_elem));
if (new_elem == NULL)
{
return -1;
}
*new_elem = *telemetry;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
myArray[i] = new_elem;
break;
}
}
return 0;
}
此版本创建传递变量的副本。
它还将指针存储在第一个可用元素中。
首先 - 我对 C 非常生疏......但是有一个项目仍然需要我生疏的技能......对于我可能编码我的解决方案的“粗略”方式表示歉意。
我的基本要求是用稍后要读取和处理的元素简单地填充一个固定的 strut 数组。该数组旨在成为“全局”数组,并从解决方案中的几个 .C 文件中使用。
我遇到的问题是,虽然有些元素添加得很好,但有些元素会被其他元素“覆盖”- 导致数组不准确,因为它不包含所有需要的填充元素。
该结构在头文件中定义为:-
typedef struct {
char* field;
char* value;} Telemetry;
数组初始化如下:-
Telemetry* myArray[5];
要添加到数组,我有一个函数可以检查下一个空“插槽”:-
int addToArray(Telemetry* telemetry)
{
counter = 0;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
break;
}
else
{
Counter++;
}
myArray[counter] = telemetry;
}
}
然后添加元素,应用程序从 CANBUS 系统接收数据 - 并解释每个值:-
//Define Struct Values
//Dialectric
char* dialectricvalueBuffer = (char*)malloc(30);
sprintf(dialectricvalueBuffer, "%f", 50.3);
Telemetry dialectricTelemetry = { .field = "DialectricConst", .value = dialectricvalueBuffer };
//Density
char* densityvalueBuffer = (char*)malloc(30);
sprintf(densityvalueBuffer, "%f", 9);
Telemetry densityTelemetry = { .field = "Density", .value = densityvalueBuffer };
//Viscosity
char* viscosityvalueBuffer = (char*)malloc(30);
sprintf(viscosityvalueBuffer, "%f", 21.9);
Telemetry viscosityTelemetry = { .field = "Viscosity", .value = viscosityvalueBuffer};
//Add values to array
addToArray(&densityTelemetry);
addToArray(&viscosityTelemetry);
addToArray(&dialectricTelemetry);
此时 myArray 的元素 0、1、2 已经填充好了。
然后一个单独的进程(读取温度)执行相同的函数以将元素添加到数组中:-
char* tempvalueBuffer = (char*)malloc(30);
sprintf(tempvalueBuffer, "%f", temperature);
Telemetry tempTelemetry = { .field = "Temperature", .value = tempvalueBuffer };
//Add values to array
addTelemetryToQueue(&tempTelemetry);
并且每一次 - 元素 2 (DialectricConst) 都会被温度元素替换。
无论我将 DialectricConst 元素移动到数组中的何处 - 它总是会尽快被温度数据替换
Telemetry tempTelemetry = { .field = "Temperature", .value = tempvalueBuffer };
执行。
任何关于原因的解释 - 将不胜感激!
有一些细节你没有显示,我必须填写一些假设:
假设...
你有一个从 CANbus 接收的函数和一些其他测量温度的函数。 你提到这些在不同的进程中,但我假设你实际上是指不同的线程或只是其他功能。否则,他们将无法在不付出额外努力的情况下共享同一个数组。
在这两个函数中,您都在堆栈上分配了局部变量。然后将它们添加到您的数组中,您只在数组中存储变量的地址但不分配额外的内存。 这意味着离开这两个函数后,局部变量不再有效。通过数组中的指针访问它们会导致未定义的行为。
假设结束
另一方面,您确实展示了添加元素的功能。 在那个函数中你有一个严重的缺陷:
int addToArray(Telemetry* telemetry)
{
counter = 0;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
break;
}
else
{
Counter++;
}
myArray[counter] = telemetry;
}
}
如果有几个元素已经拥有一个地址,则将新地址存储在每个后继者中
如果 myArray[0] != NULL
你执行 counter++;
然后 myArray[counter] = telemetry;
用有效地址填充 myArray[1]
并且在你循环的下一次迭代中你将再次执行相同的操作直到所有元素都被填充具有相同的值。
另一方面,如果您点击了一个仍然是 NULL
的条目,您将退出循环并且根本不分配任何内容。
这反过来又得出结论,您的声明“此时 myArray 的元素 0、1、2 填充得很好。”远非如此。
最后,你没有return一个值,而你承诺return一个int
。更不用说您没有为 counter
定义类型并且与 Counter
.
那么你的调用函数中有更多未定义的行为:
sprintf(densityvalueBuffer, "%f", 9);
这传递了一个 int
值,而你承诺传递一个 double
值。
您的编译器在遇到该代码时应该会显示一些警告。
固定版本为:
int addToArray(Telemetry* telemetry)
{
Telemetry *new_elem = malloc(sizeof(*new_elem));
if (new_elem == NULL)
{
return -1;
}
*new_elem = *telemetry;
//Determine next available element
for (size_t i = 0; i < 5; i++)
{
if (myArray[i] == NULL)
{
myArray[i] = new_elem;
break;
}
}
return 0;
}
此版本创建传递变量的副本。 它还将指针存储在第一个可用元素中。