![](/img/trans.png)
[英]C pointer trouble: it loses address information when returned from a function
[英]Set a pointer returned by a function to some address 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 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);
}
編譯出現以下問題:
test.c: In function ‘main’:
test.c:18:29: error: lvalue required as left operand of assignment
freeStrReturnPointer(t) = NULL;
我的問題是:如果函數freeStrReturnPointer返回一個指針char *,為什么不能將其設置為NULL? 以下絕對可以工作:
char* p;
p = NULL;
這里有什么區別? 為什么不能立即為返回的指針分配值?
警告:我意識到我可以在函數中將指針設置為null,但這不是問題的重點。
您不能這樣做,因為表達式freeStrReturnPointer(t)
返回一個r值,該值需要分配給一個變量,以便其壽命超出包含它的完整表達式。 實際上,將其分配為“ null”沒有明顯的副作用,並且很可能是程序員的錯誤,因此該語言將其視為錯誤。
相反,你應該做
char * p = freeStrReturnPointer(t);
p = NULL;
然后,在兩個表達式中p
都是l值, freeStrReturnPointer(t)
在第一個表達式中是r值,而NULL
在第二個表達式中是r值。
或者,您可以將freeStrReturnPointer(t)
視為void函數,而忽略結果(因為無論如何都不使用它,因此沒有理由將其設置為NULL
):
(void) freeStrReturnPointer(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
。
好吧,您想要做的事情等效於以下內容:
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);
};
在main()中:
char **p = freeStrReturnPointer(t);
printf("%p\n", t->str);
*p = NULL;
printf("%p\n", t->str);
然后將輸出類似:
0x012345678901
0x0
freeStrReturnPointer()
返回一個值(更正確的值是正確的值)。 在您的情況下,它是一個指針,但是還是一個值。 正如編譯器告訴您的那樣,您基本上是在嘗試更改=
運算符的工作方式。 賦值運算符的左側需要某種變量,而右側則需要一個值(可以再次為變量)。 您在這里的問題不僅限於指針。 甚至嘗試使用基本類型或對象,仍然會出現此錯誤。
似乎在freeStrReturnPointer(struct this * t)
,使用t->str
所做的操作與在main中創建的變量無關,並且返回的內容實際上是一個右值(並且不能為右值賦值) 。 我會改用一個指向指針的指針: freeStrReturnPointer(struct this ** t)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.