动态 C 结构中的重叠和过长的整数值

Overlapping and too long integer values in dynamic c structs

我有以下问题。 我需要创建一个具有动态长度的保存状态列表。这就是为什么我决定通过定义一些结构并将动态创建的结构连接在一起以构建可以动态扩展的结构列表等来创建列表的原因。 但是,有些事情似乎根本行不通。先贴出相关代码:

saves.h:

#ifndef SAVES_H
#include<time.h>
#define SAVES_H
#define SVS_STRLEN 500
#define SVS_FILE "savefile.dat"
#define True 1
#define False 0
typedef struct SVS_STATE SVS_STATE;
typedef struct SVS_STATES SVS_STATES;

struct SVS_STATE {
    int i_playfield[6][7];
    int i_turn;
    time_t i_time;
    void *next;
};

struct SVS_STATES {
    SVS_STATE *states;
    int count;
    int loaded;
};

void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time);
void SVS_Debug_State(SVS_STATE *state);
void SVS_Format_State(SVS_STATE *state, char text[]);
SVS_STATE *SVS_Get_State(int number);
#endif

saves.c:

#include "saves.h"
#include<string.h>
#include<time.h>

SVS_STATE *SVS_Get_State(int number)
{
    int i = 1;
    SVS_STATE *state;
    if (svs_current_state.loaded == False) return NULL;
    if (number > svs_current_state.count) return NULL;
    state = svs_current_state.states;
    printf("printing state 1:");
    SVS_Debug_State(state);
    while( i < number)
    {
        i++;
        state = (SVS_STATE*)(state->next);
        printf("printing state %i:", i);
        SVS_Debug_State(state);
    }
    return state;
}

void SVS_Format_State(SVS_STATE *state, char text[])
{
    int i, j;
    if (svs_current_state.loaded == False) return;
    text[0] = '[=11=]';
    strcat(text, "{[=11=]");
    for (i = 0; i < X_SIZE; i++)
    {
        strcat(text, "{[=11=]");
        for(j = 0; j < Y_SIZE; j++)
        {
            strcat(text, "%i,[=11=]");
            sprintf(text, text, state->i_playfield[i][j]);
        }
        strcat(text, "}[=11=]");
    }
    strcat(text, "};%i;%i\n[=11=]");
    sprintf(text, text, state->i_turn, state->i_time);
    printf("\nFormatted state:%s\n", text);
}

void SVS_Debug_State(SVS_STATE *state)
{
    char text[SVS_STRLEN];
    SVS_Format_State(state, text);
    printf("%s\n", text);
}

void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time)
{
    int i, j;
    SVS_STATE *laststate, *newstate;
    newstate = (SVS_STATE*)malloc(sizeof(SVS_STATE));
    printf("adding state with time:%i\n", i_time);
    if (svs_current_state.loaded == False) return;
    for (i = 0; i < 6; i++)
        for (j = 0; j < 7; j++)
            newstate->i_playfield[i][j] = i_playfield[i][j];
    newstate->i_turn = i_turn;
    newstate->i_time = i_time;
    newstate->next = NULL;
    printf("initialized state:");
    SVS_Debug_State(newstate);
    if (svs_current_state.coun > 0)
    {
        laststate = SVS_Get_State(svs_current_state.count);
        laststate->next = (void*)newstate;
    } else
        svs_current_state.states=newstate;
    svs_current_state.count++;
}

int main()
{
    int i_playfield[6][7] = {0};
    // mark saves library as loaded here, but removed function, since it
    // just sets svs_current_state.loaded (which is the global struct of
    // type SVS_STATES) to 1
    SVS_Add_State(i_playfield, 1, time(NULL));
    i_playfield[0][0] = 2;
    SVS_Add_State(i_playfield, 2, time(NULL));
    return 0;
}

我在这些函数中使用printf和Debug_State调用时遇到的实际问题: - 我给出的 i_time 在 Add_State() 中正确地打印了一次。意味着这是一个合法的时间和东西,但是在使用 Format_State() 创建完整状态后打印出来时,字符串是 50% 长并且最后一部分显示两次,例如: 如果时间是12345678,在Add_State调试时显示正确,但Format_State()显示123456785678。 - 第二个问题:第一个状态添加的作品,或多或少,很好。但是在添加第二个之后,打印第一个状态(通过使用 Get_State 检索并使用 Format_State 格式化)打印两种状态的混合,例如这样的东西:

state 1: {{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}...
{0,0,0,0,0,0}};1;123456785678
state 2: {{0,0,0,0,0,0}{0,0,0,0,0,0}...
{0,0,0,0,0,0}};2;1234567856785678,0}{0,0,0,0,0,0}...

感谢阅读。

这些电话

sprintf(text, text, ...

调用未定义的行为,因为目标缓冲区和其他参数之一重叠。

来自POSIX specs to sprintf()

If copying takes place between objects that overlap as a result of a call to sprintf() [...], the results are undefined.