简体   繁体   English

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

[英]Set a pointer returned by a function to some address C

I was writing some C code and I got the following problem. 我正在编写一些C代码,但遇到以下问题。 Suppose we have this really simple program: 假设我们有一个非常简单的程序:

#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);
}

Compilation gives the following problem: 编译出现以下问题:

test.c: In function ‘main’:
test.c:18:29: error: lvalue required as left operand of assignment
     freeStrReturnPointer(t) = NULL;

My question is: If the function freeStrReturnPointer returns a pointer char*, why can I not set it to NULL? 我的问题是:如果函数freeStrReturnPointer返回一个指针char *,为什么不能将其设置为NULL? The following would definitely work: 以下绝对可以工作:

char* p;
p = NULL;

What is the difference here? 这里有什么区别? Why can I not assign a value to the returned pointer immediately? 为什么不能立即为返回的指针分配值?

Caveat: I realize I can just set the pointer to null in the function, but that is not the point of the question. 警告:我意识到我可以在函数中将指针设置为null,但这不是问题的重点。

You can't do that because the expression freeStrReturnPointer(t) returns an r-value, which needs to be assigned to a variable in order for its lifetime to extend beyond the full expression that contains it. 您不能这样做,因为表达式freeStrReturnPointer(t)返回一个r值,该值需要分配给一个变量,以便其寿命超出包含它的完整表达式。 Assigning it to "null" literally has no visible side effects and is most likely a programmer mistake, so the language treats it as an error. 实际上,将其分配为“ null”没有明显的副作用,并且很可能是程序员的错误,因此该语言将其视为错误。

Instead you should do 相反,你应该做

char * p = freeStrReturnPointer(t);
p = NULL;

Then, in both expressions p is the l-value, and freeStrReturnPointer(t) is the r-value in the first, and NULL is the r-value in the second. 然后,在两个表达式中p都是l值, freeStrReturnPointer(t)在第一个表达式中是r值,而NULL在第二个表达式中是r值。

Alternatively, you could treat freeStrReturnPointer(t) as a void function and just ignore the result (since you don't use it anyways, there's no reason to set it to NULL ): 或者,您可以将freeStrReturnPointer(t)视为void函数,而忽略结果(因为无论如何都不使用它,因此没有理由将其设置为NULL ):

(void) freeStrReturnPointer(t);

I think what you mean to do is return a pointer to the pointer, then dereference that and set the original pointer to NULL . 我认为您的意思是返回一个指向该指针的指针,然后取消对该指针的引用并将原始指针设置为NULL

so in your code I would write: 所以在您的代码中,我会写:

#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);
}

Which would set str to NULL after freeing it. 释放后会将str设置为NULL

currently you are just returning the actual pointer to char , not a pointer to the storage of the pointer to char . 目前你是刚刚返回的实际指针char ,而不是一个指针指向的存储char

Well, what you're trying to do is equivalent of the following: 好吧,您想要做的事情等效于以下内容:

char *p = freeStrReturnPointer(t); 
p = NULL; 

which will not reset t->str ! 这不会重置t->str Your freeStrReturnPointer() function is returning a char* value that points to a string. 您的freeStrReturnPointer()函数正在返回一个指向字符串的char*值。 If you assign to it, then you overwrite where it points to, making it useless code. 如果分配给它,则将覆盖它指向的位置,从而使它无用的代码。

If you do: 如果您这样做:

char *p = freeStrReturnPointer(t); 
printf("%p\n", t->str);
p = NULL; 
printf("%p\n", t->str);

You'll get: 你会得到:

0x012345678901
0x012345678901

as output. 作为输出。

If you want to reset t->str you then need to use a double pointer: 如果要重置t->str ,则需要使用双指针:

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

and within main(): 在main()中:

char **p = freeStrReturnPointer(t);
printf("%p\n", t->str);
*p = NULL;
printf("%p\n", t->str);

which will then output something like: 然后将输出类似:

0x012345678901
0x0

freeStrReturnPointer() is returning a value (right value to be more precise). freeStrReturnPointer()返回一个值(更正确的值是正确的值)。 In your case it's a pointer but a value nonetheless. 在您的情况下,它是一个指针,但是还是一个值。 As the compiler is telling you, you are basically trying to alter the way the = operator is working. 正如编译器告诉您的那样,您基本上是在尝试更改=运算符的工作方式。 Assignment operator requires a variable of some sort on the left and a value (which can again be a variable) on the right. 赋值运算符的左侧需要某种变量,而右侧则需要一个值(可以再次为变量)。 Your problem here is not restricted to pointers. 您在这里的问题不仅限于指针。 Try using even basic types or an object and you will still get this error. 甚至尝试使用基本类型或对象,仍然会出现此错误。

It seems that in the freeStrReturnPointer(struct this * t) what you do with t->str has no incidence on the variable that you created in main, and what you return is actually an rvalue (and you cannot assign something to an rvalue). 似乎在freeStrReturnPointer(struct this * t) ,使用t->str所做的操作与在main中创建的变量无关,并且返回的内容实际上是一个右值(并且不能为右值赋值) 。 I would use a pointer to pointer instead : freeStrReturnPointer(struct this ** t) 我会改用一个指向指针的指针: freeStrReturnPointer(struct this ** t)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM