【问题标题】:C pointer address changes without assignmentC 指针地址更改无需赋值
【发布时间】:2013-09-26 16:51:28
【问题描述】:

我正在这里处理大学作业,但遇到了问题。我正在尝试使用 for 循环将字符串输入存储在结构内的某个点。稍后我打算使用指向数据存储位置的指针来获取字符串。现在的问题是,当我在我的 for 循环中继续前进时,点的地址也发生了变化。这段代码:

printf("B: %p\n", txt->point);
for(i = 0; i < input_sz; i++)
{
    txt->point[i] = input[i];
}
printf("A: %p\n", txt->point);

给出输出:

B: 0x7fc111803200
A: 0x7fc111803265

其中 B 是前值,A 是复制后值。

任何调试此问题的帮助将不胜感激!


编辑:这里还有一些代码:

结构:

struct text_storage {
    char* start;
    char* point;
    char* end;
} typedef text_t;

初始化函数:

text_t* text_init(void *memory, size_t size)
{
    text_t* to_return;
    if(size < sizeof(text_t))
    {
        return NULL;
    }
    to_return = (text_t*) memory;
    to_return->start = to_return;

    to_return->end = to_return->start + size;
    to_return->point = to_return->start;

    printf("Start: %p, point: %p, end: %p, end-start: %d\n", to_return->start, to_return->point, to_return->end, (to_return->end - to_return->start));


    return to_return;
}

发生错误的文本存储方法:

int text_store_entry(text_t *txt, const char *input, size_t input_sz)
{
    int to_return;
    char* begin = txt->point;
    int i;

    if(input_sz > (txt->end - txt->point))
    {
        return -1;
    }

    printf("Start: %p, point: %p, end: %p, end-start: %d\n", txt->start, txt->point, txt->end, (txt->end - txt->start));


    printf("B: %p\n", txt->point);
    for(i = 0; i < input_sz; i++)
    {
        txt->point[i] = input[i];
    }
    printf("A: %p\n", txt->point);

}

主要功能(仅用于测试目的):

int main(int argc, char* argv[])
{
    void* memory = malloc(10000);
    char* a = "hei pa deg din trekkbasun";
    text_t* txt;
    int memoverwritten;

    txt = text_init(memory, 10000);

    memoverwritten = text_store_entry(txt, a, (size_t)26);


    printf("got through\n");
    return 0;
}

【问题讨论】:

  • 显示声明和其他代码。 - 可能是未定义的行为
  • 现在添加了更多代码。谢谢@GrijeshChauhan
  • 但是我看不到你在哪里调用text_store_entry()函数?
  • 那个在main-function里面,我加一下。它仅用于测试目的。
  • to_return-&gt;start = to_return; 看起来不对 startchar* 指针,to_returntext_t* 类型。

标签: c pointers struct pointer-arithmetic


【解决方案1】:

这个问题很可能是由struct text_storage 类型的结构的初始化引起的。这种结构包含三个指向文本的指针。每个指针都应该被初始化,可能使用malloc。您的 text_init 函数无法正确执行此操作。 实际上,start 指针的存放位置与您要使用的内存的第一个字节重叠。

我猜你需要这样的结构:

typedef struct text_storage {
    char* start;
    char* point;
    char* end;
    char* data;
} text_t;

用这样的函数初始化:

text_t text_init(void *memory, size_t size)
{
  text_t to_return;
  to_return.data = (char *) memory;
  to_return.start = to_return.data;
  to_return.end = to_return.start + size;
  to_return.point = to_return.start;
  return to_return;
}

【讨论】:

  • 赋值指定我们被允许使用的唯一堆空间是传递给 text_init 函数的堆空间。我们不允许在这个块之外保留堆内存。恐怕这让我没有malloc :(
  • 好的,没有malloc,见上文。如果您希望memory 存储完整的结构,您需要一个具有可变大小的最后一个字段的结构,请参阅here
  • 谢谢!所以你正在使用另一个指向数据的指针?您如何考虑将开始和结束指针更改为空长度数组?那么它们会占用 0 个字节并且只指向内存中的某个地方,对吧?
  • 同一结构中不能有两个零长度数组。您可以只有一个这样的字段,并且它必须是最后一个。这是一个技巧,如果您的结构的实际长度您不知道但只有它们的第一个字段,那么它很有用。如果可以的话,避免它。
  • 谢谢,我在这里尝试听从您的建议,但在to_return.end = to_return.start + size; 行出现编译器错误。知道为什么吗?我不明白为什么它不起作用。
【解决方案2】:

在循环中打印 txt->point 并查看它发生变化的点。我猜它在分配给 txt->point[0] 时会发生变化。我对 printf 并不完全熟悉,所以我不确定它会为您打印什么,但数组的名称引用了第一个位置。如果 printf 打印出一个指针,则 txt->point[i] 始终是一个 char 指针,并且 printf 可能正在取消对 txt->point 的引用,这将使它成为第一个条目,然后在那里显示您分配的地址当您将点更改为 input[i] 时。

【讨论】:

  • 这似乎是对的。该点的地址在进入第一次迭代时更改为新值(从开始开始+65),并在整个循环中保持该值。在循环内打印 txt->point[i] 的地址时,我可以看到它每次迭代移动 4 个字节。这是有道理的,因为我们正在存储字符。
  • 在这种情况下,将您的 printf 语句更改为 print &txt->point[0],希望它保持不变,表明您的阵列没有移动。虽然我没想到 printf 会像你说的那样在每次迭代中都发生变化,所以让我想知道。
  • 这种调试没必要,问题很清楚。在初始化结构的方式中,txt&amp;(txt-&gt;start)txt-&gt;start 都指向同一个地址(memory)。当您开始添加文本时,您会删除 txt-&gt;start 的值。
猜你喜欢
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 2011-10-27
  • 2015-08-09
相关资源
最近更新 更多