将函数返回的指针设置为某个地址C

将函数返回的指针设置为某个地址C,c,C,我正在写一些C代码,我遇到了以下问题。假设我们有一个非常简单的程序: #include <stdio.h> #include <stdlib.h> struct this { char* str; }; char* freeStrReturnPointer(struct this * t) { free(t->str); return t->str; }; int main() { // standard mallocin

我正在写一些C代码,我遇到了以下问题。假设我们有一个非常简单的程序:

#include <stdio.h>
#include <stdlib.h>

struct this {
    char* str;
};

char* freeStrReturnPointer(struct this * t) {
    free(t->str);
    return t->str;
};

int main() {
    // standard mallocing going on
    struct this* t = malloc(sizeof(struct this));
    t->str = malloc(sizeof(char)*10);
    // here is the problematic part!
    freeStrReturnPointer(t) = NULL;
    // end of problematic part
    free(t);
    exit(0);
}
我的问题是:如果函数freestrruentpointer返回指针char*,为什么我不能将其设置为NULL?以下措施肯定会奏效:

char* p;
p = NULL;
这里有什么区别?为什么我不能立即为返回的指针赋值


警告:我意识到我可以在函数中将指针设置为null,但这不是问题的关键。

您不能这样做,因为表达式freeStrReturnPointert返回一个r值,需要将该值赋给一个变量,以便其生存期扩展到包含它的完整表达式之外。将其赋值为null实际上没有明显的副作用,很可能是程序员的错误,因此该语言将其视为错误

相反,你应该这样做

char * p = freeStrReturnPointer(t);
p = NULL;
然后,在这两个表达式中,p是l值,freeStrReturnPointert是第一个表达式中的r值,NULL是第二个表达式中的r值

或者,您可以将freeStrReturnPointert视为一个void函数,忽略结果,因为您无论如何都不使用它,所以没有理由将其设置为NULL:


不能这样做,因为表达式freeStrReturnPointert返回一个r值,需要将该值赋给变量,以便使其生存期超出包含它的完整表达式。将其赋值为null实际上没有明显的副作用,很可能是程序员的错误,因此该语言将其视为错误

相反,你应该这样做

char * p = freeStrReturnPointer(t);
p = NULL;
然后,在这两个表达式中,p是l值,freeStrReturnPointert是第一个表达式中的r值,NULL是第二个表达式中的r值

或者,您可以将freeStrReturnPointert视为一个void函数,忽略结果,因为您无论如何都不使用它,所以没有理由将其设置为NULL:


freeStrReturnPointer返回的是一个更精确的正确值。在您的例子中,它是一个指针,但仍然是一个值。正如编译器告诉您的,您基本上是在尝试改变=运算符的工作方式。赋值运算符需要在左侧显示某种类型的变量,在右侧显示一个值,该值也可以是变量。这里的问题不限于指针。即使尝试使用基本类型或对象,也会出现此错误。

freestrruentpointer返回的值更准确。在您的例子中,它是一个指针,但仍然是一个值。正如编译器告诉您的,您基本上是在尝试改变=运算符的工作方式。赋值运算符需要在左侧显示某种类型的变量,在右侧显示一个值,该值也可以是变量。这里的问题不限于指针。即使尝试使用基本类型或对象,您仍然会遇到此错误。

在freeStrReturnPointerstruct中,您使用t->str所做的操作与您在main中创建的变量没有关联,并且您返回的实际上是一个右值,您无法为右值赋值。我会使用指向指针的指针:freeStrReturnPointerstruct this**t

在freeStrReturnPointerstruct this*t中,您使用t->str所做的操作与您在main中创建的变量没有关联,并且您返回的实际上是一个右值,您无法为右值赋值。我会使用指向指针的指针:freestrrreturnpointerstructt this**t

我认为您的意思是返回指向指针的指针,然后取消引用并将原始指针设置为NULL

因此,在您的代码中,我将编写:

#include <stdio.h>
#include <stdlib.h>

struct this {
    char* str;
};

char** freeStrReturnStrPointer(struct this * t) {
    free(t->str);
    return &t->str;
};

int main(){
    struct this* t = malloc(sizeof(struct this));
    t->str = malloc(sizeof(char)*10);
    *freeStrReturnStrPointer(t) = NULL;
    free(t);
}
这将在释放str后将其设置为NULL


当前,您只是返回指向char的实际指针,而不是指向char指针存储的指针。

我认为您的意思是返回指向该指针的指针,然后取消引用并将原始指针设置为NULL

因此,在您的代码中,我将编写:

#include <stdio.h>
#include <stdlib.h>

struct this {
    char* str;
};

char** freeStrReturnStrPointer(struct this * t) {
    free(t->str);
    return &t->str;
};

int main(){
    struct this* t = malloc(sizeof(struct this));
    t->str = malloc(sizeof(char)*10);
    *freeStrReturnStrPointer(t) = NULL;
    free(t);
}
这将在释放str后将其设置为NULL


当前,您只是返回指向char的实际指针,而不是指向指向char的指针存储的指针。

那么,您尝试执行的操作相当于以下操作:

char *p = freeStrReturnPointer(t); 
p = NULL; 
这将不会重置t->str!freeStrReturnPointer函数返回指向字符串的char*值。如果指定给它,则覆盖它指向的位置,使其成为无用代码

如果您这样做:

char *p = freeStrReturnPointer(t); 
printf("%p\n", t->str);
p = NULL; 
printf("%p\n", t->str);
您将获得:

0x012345678901
0x012345678901
作为输出

如果要重置t->str,则需要使用双指针:

char** freeStrReturnPointer(struct this * t) {
    free(t->str);
    return &(t->str);
};
在主要区域内:

char **p = freeStrReturnPointer(t);
printf("%p\n", t->str);
*p = NULL;
printf("%p\n", t->str);
然后输出如下内容:

0x012345678901
0x0

好吧,你正在尝试做的事情相当于以下几点:

char *p = freeStrReturnPointer(t); 
p = NULL; 
这将不会重置t->str!freeStrReturnPointer函数返回指向字符串的char*值。如果指定给它,则覆盖它指向的位置,使其成为无用代码

如果您这样做:

char *p = freeStrReturnPointer(t); 
printf("%p\n", t->str);
p = NULL; 
printf("%p\n", t->str);
您将获得:

0x012345678901
0x012345678901
< p> 作为输出

如果要重置t->str,则需要使用双指针:

char** freeStrReturnPointer(struct this * t) {
    free(t->str);
    return &(t->str);
};
在主要区域内:

char **p = freeStrReturnPointer(t);
printf("%p\n", t->str);
*p = NULL;
printf("%p\n", t->str);
然后输出如下内容:

0x012345678901
0x0

您可以分配给变量,因为变量是一个容器。函数调用只返回一个值,分配给它是没有意义的。它是什么类型无关紧要。这就像尝试做a+b=3。当您分配给函数时,您希望NULL放在哪里;返回t->str;导致未定义的行为。您可能不会使用释放的指针的值。您似乎对C的工作方式有根本性的误解。我建议您阅读有关可以分配给变量的内容,因为变量是一个容器。函数调用只返回一个值,分配给它是没有意义的。它是什么类型无关紧要。这就像尝试做a+b=3。当您分配给函数时,您希望NULL放在哪里;返回t->str;导致未定义的行为。您可能不会使用释放的指针的值。您似乎对C的工作方式有根本性的误解。我建议您阅读一下,如果忽略返回值,您应该在函数调用前加上void,这样编译器就不会生气。尽管我同意您的大部分解释,但您应该做的部分是错误的。你在那里说的:char*p=freestrrurnpointert;p=NULL;,这里p是一个右值,它的生存期不能超过表达式。通过显式执行所做的一切就是让程序员错误地理解传递错误的构造!使用字符**执行此操作是一种可以正确解决问题的方法,显然,将其设为void而不将其置为null更好。如果忽略返回值,则应在函数调用前加上void前缀,以便编译器不会生气。尽管我同意您的大部分解释,但您应该执行的部分是错误的。你在那里说的:char*p=freestrrurnpointert;p=NULL;,这里p是一个右值,它的生存期不能超过表达式。通过显式执行所做的一切就是让程序员错误地理解传递错误的构造!使用char**进行操作是一种能够正确解决问题的方法,显然,使其无效而不使其为空更好。