C 函数调用后,结构指针值不会更改

C 函数调用后,结构指针值不会更改,c,pointers,struct,C,Pointers,Struct,编辑*:我知道有类似的问题,但由于这是一项实践作业,因此会给出函数签名,我只允许更改函数体。因此,我不能像在类似线程上那样更改函数参数或返回类型。提前谢谢 我真的对我正在写的程序感到困惑。我基本上是在写一个函数,它有两个指向结构的指针,结构有一个int组件和一个字符数组组件。该函数附加两个字符数组组件以返回结构(类似于strcat)。问题是,虽然函数会更新结构的数组部分,但int部分不会。有人能解释为什么吗?函数newText创建一个新的结构文本,并将结构的数组设置为函数的参数。它还将容量设置为

编辑*:我知道有类似的问题,但由于这是一项实践作业,因此会给出函数签名,我只允许更改函数体。因此,我不能像在类似线程上那样更改函数参数或返回类型。提前谢谢

我真的对我正在写的程序感到困惑。我基本上是在写一个函数,它有两个指向结构的指针,结构有一个int组件和一个字符数组组件。该函数附加两个字符数组组件以返回结构(类似于strcat)。问题是,虽然函数会更新结构的数组部分,但int部分不会。有人能解释为什么吗?函数newText创建一个新的结构文本,并将结构的数组设置为函数的参数。它还将容量设置为24。如果字符串参数的长度大于24,则会将容量加倍,直到合适为止。append函数追加两个字符串,然后用新追加的字符串调用newText,并将t1设置为等于newText的返回值。我在append函数的末尾有print语句来说明它是有效的,并且值是正确的,但是在main中,调用函数后,t->capacity再次变为24,而不是48,而t->content是正确的。这是我的密码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>


struct text { int capacity; char *content; };

typedef struct text text;


text *newText(char *s) {

  text *t = malloc(sizeof(text));
  t->capacity = 24;

  while (strlen(s) + 1 > t->capacity) {t->capacity = t->capacity * 2;} 
  t->content = malloc(t->capacity);
  strcpy(t->content, s);

  return t; 
}

void append(text *t1, text *t2) {
  int length1 = strlen(t1->content);
  int length2 = strlen(t2->content);
  int lengths = length1 + length2;


  for (int i = length1; i < length1 + length2; i++){
  t1->content[i] = t2->content[i - length1];
  t1->content[i + 1] = '\0';                }

  char text[100];
  strcpy(text, t1->content);


  t1 = newText(text);

  printf("%s \n", t1->content);
  printf("%d \n", t1->capacity);

}

int main () {
  text *t = malloc(sizeof(text));
  text *t1 = malloc(sizeof(text));

  t = newText("carpet");
  t1 = newText("789012345678901234");
  append(t, t1);
  printf("%d\n", t->capacity);
}
#包括
#包括
#包括
#包括
#包括
结构文本{int capacity;char*content;};
typedef结构文本;
文本*newText(字符*s){
text*t=malloc(sizeof(text));
t->容量=24;
而(strlen(s)+1>t->capacity){t->capacity=t->capacity*2;}
t->content=malloc(t->capacity);
strcpy(t->content,s);
返回t;
}
无效附加(文本*t1,文本*t2){
int length1=strlen(t1->content);
int length2=strlen(t2->content);
整数长度=长度1+长度2;
对于(int i=length1;i内容[i]=t2->内容[i-长度1];
t1->内容[i+1]='\0';}
字符文本[100];
strcpy(文本,t1->content);
t1=新文本(文本);
printf(“%s\n”,t1->content);
printf(“%d\n”,t1->容量);
}
int main(){
text*t=malloc(sizeof(text));
text*t1=malloc(sizeof(text));
t=新文本(“地毯”);
t1=新文本(“7890123456789001234”);
附加(t,t1);
printf(“%d\n”,t->capacity);
}
在这里,您将
t1
设置为新的
text
。但是,
t1
指向的原始
文本在这里没有改变。它仍然指向同一个地方。传递给函数的指针是原始指针的副本,因此即使
t1
指向新的
文本,原始指针也不会

所以当你在这里打印的时候

  printf("%d\n", t->capacity);
您仍然可以获得容量的旧值。或者更确切地说,是
t1
的容量。而在这里

printf("%s \n", t1->content);
printf("%d \n", t1->capacity);
您正在打印新的
t1
内容和
容量,函数结束后指针将丢失

例如,您可以通过返回该指针来修复该问题。将签名更改为

text* append(text *t1, text *t2)
在函数的末尾:

return t1;
然后你更新了
t1
,所以改变这个

append(t, t1);

此外,还要注意内存泄漏。现在,在
append
中,您将指针指向两个有效的
文本
,并分配一个新的
文本
,在函数结束时,您仍然只有两个指向
文本
的指针,并且没有
释放
。这向我们表明,其中一个被泄露了

编辑:

如果无法更改函数的签名,则无法返回新的
文本
,或使用双指针将其传递出去。在这种情况下,我建议不要制作新的
文本
,而只是更改
t1
。使用
realloc
可以更改缓冲区的大小(实际上,它可能只是分配一个新的缓冲区,复制数据并释放旧的缓冲区),这样就可以附加
t2
的内容

void append(text *t1, text *t2) {
    int length1 = strlen(t1->content);
    int length2 = strlen(t2->content);
    int lengths = length1 + length2;                // calculate the required length. You can change this to have some "reserve" such as in newText. In this example, it will be 24

    t1->content = realloc(t1->content, lengths);        // set the correct size for the buffer

    for (int i = length1; i < length1 + length2; i++) {
        t1->content[i] = t2->content[i - length1];
        t1->content[i + 1] = '\0';
    }   // append the second string

    t1->capacity = lengths;
    printf("%s \n", t1->content);
    printf("%d \n", t1->capacity);
}
void追加(text*t1,text*t2){
int length1=strlen(t1->content);
int length2=strlen(t2->content);
int length=length1+length2;//计算所需的长度。您可以将其更改为具有一些“保留”,例如在newText中。在本例中,它将是24
t1->content=realloc(t1->content,length);//为缓冲区设置正确的大小
对于(int i=length1;i内容[i]=t2->内容[i-长度1];
t1->内容[i+1]='\0';
}//追加第二个字符串
t1->容量=长度;
printf(“%s\n”,t1->content);
printf(“%d\n”,t1->容量);
}

要修改函数中的指针并将其传回,必须传递指针的地址,例如:

void test(char** ppTest) {
    //Is anything valid passed?
    if ( ppTest == NULL ) {
        return;
    }
    *ppTest = "Hello World";
}

int main(void) {
    char* pTest = NULL;
    printf("Before function call pTest: %s\n", (pTest == NULL) ? "NULL" : pTest);
    test(&pTest); // Must pass the address of the pointer
    printf("After function call pTest: %s\n", (pTest == NULL) ? "NULL" : pTest);
    return 0;
}

简而言之,我的问题是,为什么在main中的append函数之后t->capacity等于24,因为append运行时的print语句显示t->capacity为48。显然是@UnholySheepIn命令的副本,要修改并传回指针,必须传递指针的地址,因此,将原型更改为**。请注意,代码中存在内存泄漏:在main()的开头,用malloc指定t和t1,然后用newText()覆盖它们的值。您应该让它们未初始化,或者将它们设置为NULL,或者在newText()之前调用free()。感谢您的回答,我知道这是一个类似的问题,但因为我无法更改函数签名(因为这是一个实践赋值,其中签名是给定的,我们只允许修改主体)我无法使用另一个问题中提供的答案,即改变函数,使其接受指向指针的指针或返回指针。哦,太好了,现在我明白了为什么会发生这种情况。感谢您的回复,但是,此代码是
void append(text *t1, text *t2) {
    int length1 = strlen(t1->content);
    int length2 = strlen(t2->content);
    int lengths = length1 + length2;                // calculate the required length. You can change this to have some "reserve" such as in newText. In this example, it will be 24

    t1->content = realloc(t1->content, lengths);        // set the correct size for the buffer

    for (int i = length1; i < length1 + length2; i++) {
        t1->content[i] = t2->content[i - length1];
        t1->content[i + 1] = '\0';
    }   // append the second string

    t1->capacity = lengths;
    printf("%s \n", t1->content);
    printf("%d \n", t1->capacity);
}
void test(char** ppTest) {
    //Is anything valid passed?
    if ( ppTest == NULL ) {
        return;
    }
    *ppTest = "Hello World";
}

int main(void) {
    char* pTest = NULL;
    printf("Before function call pTest: %s\n", (pTest == NULL) ? "NULL" : pTest);
    test(&pTest); // Must pass the address of the pointer
    printf("After function call pTest: %s\n", (pTest == NULL) ? "NULL" : pTest);
    return 0;
}