此函式不回傳預期結果(交換a和b)。
#include<stdio.h>
#include<stdlib.h>
void swap_one(int *x, int *y) {
int *tmp;
tmp = x;
x = y;
y = tmp;
printf("x = %d y = %d\n", *x, *y);
}
void swap_two(int *x, int *y) {
}
int main() {
int a = 5;
int b = 100;
printf("Before a = %d b = %d\n\n", a, b);
int *p = (int *) malloc(sizeof(int));
int *q = (int *) malloc(sizeof(int));
p = &a;
q = &b;
swap_one(p, q);
printf("After a = %d b = %d\n", a, b);
return 0;
}
但下面的代碼按預期作業。
#include <stdlib.h>
#include <stdio.h>
typedef struct ListElmt_ {
void *data;
struct ListElmt_ *next;
} ListElmt;
typedef struct List_ {
int size;
int (*match) (const void *key1, const void *key2);
void (*destroy) (void *data);
ListElmt *head;
ListElmt *tail;
} List;
void list_init (List *list) {
list->size = 0;
list->match = NULL;
list->destroy = NULL;
list->head = NULL;
list->tail = NULL;
}
int list_ins_next(List *list, ListElmt *element, void *data) {
ListElmt *new_element;
/* Alocate storage for the element. */
if ((new_element = (ListElmt *) malloc(sizeof(ListElmt))) == NULL) return -1;
/* new_element->data is of type void *. So we use (void *) data */
new_element->data = (void *)data;
if (element == NULL) {
/* Handle insertion at the head of the list */
if (list->size == 0) list->tail = new_element;
new_element->next = list->head;
list->head = new_element;
} else {
if (element->next == NULL) list->tail = new_element;
new_element->next = element->next;
element->next = new_element;
}
list->size ;
return 0;
}
/* Print the list */
static void print_list(const List *list) {
ListElmt *element;
int *data;
int i;
/* Display the linked list */
fprintf(stdout, "List size is %d\n", list->size);
i = 0;
element = list->head;
while (1) {
data = element->data;
fprintf(stdout, "list[d] = d\n", i, *data);
i ;
if (element->next == NULL) {
break;
} else {
element = element->next;
}
}
}
int main(int argc, char **argv) {
List list;
ListElmt *element;
int *data;
int i;
/* list = (List *) malloc(sizeof(List)); */
/* Initialize the linked list */
List *listPtr;
listPtr = &list;
list_init(listPtr);
/* Perform some linked list operations */
element = listPtr->head;
for (i = 10; i > 0; i--) {
if ( (data = (int *) malloc(sizeof(int))) == NULL) return 1;
*data = i;
if (list_ins_next(listPtr, NULL, data) != 0) return 1;
}
print_list(listPtr);
fprintf(stdout, "Value in *data is:%d\n", *data);
return 0;
}
問題是:在swap_one函式中,x=y類似于new_element->next = element->nextor element->next = new_element。為什么做new_element->next = element->next和element->next = new_element作業但x =y在swap_one函式中不交換a和b?
很抱歉有很多代碼,但我真的對這個感到困惑。
謝謝。
uj5u.com熱心網友回復:
該指標傳遞的價值。交換這些變數中保存的指標值并不能實作它們指向的資料的交換。
假設
&p地址為 0x1000,&q地址為 0x1004。現在,您呼叫
swap_one(&p, &q);-- 指標的x值為 0x1000,指標的y值為 0x1004。現在交換指標值。
x現在是西班牙語-多米尼加共和國這點q和y現在的0x1000這點p。然而,p并q從未在記憶中移動過。您只更改了存盤在指標中的值。當函式回傳時,這些指標超出范圍。
p并且q仍然保持與以前相同的內容,因為您從一開始就沒有修改它們。
因此,要交換它們指向的值,您必須取消參考指標以獲取實際資料。
int tmp = *x;
*x = *y;
*y = tmp;
將此與您的鏈接串列示例進行對比。在該示例中,您有一個指向結構的指標,并且正在修改其next成員。這實際上修改了記憶體中的指標,因為這是您的鏈表所在的位置以及它如何存盤值。
但是,如果您將這些指標指向某個假設函式,則會出現同樣的問題:swap_next(node **x, node **y);--x并且y只是指向指標值的區域變數。如果您交換它們,它們不會修改除自身以外的任何內容。所以同樣的修復適用:要更改指向的資料,您必須跟隨指標。
uj5u.com熱心網友回復:
您的swap_one函式只是交換傳遞給函式的指標值,而不是指標指向的值。因此,您所做的任何更改都不會反映在函式之外。
您需要取消參考這些指標以讀取/寫入它們指向的內容。
void swap_one(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
printf("x = %d y = %d\n", *x, *y);
}
在list_ins_next函式中,您正在更改指標指向的內容,因此可以在函式外部看到更改。
uj5u.com熱心網友回復:
變數x和y是 的區域變數swap_one()。這是呼叫swap_one()函式時發生的情況:
p = &a;
q = &b;
p (pointer) q (pointer)
--- ---
| |--- | |---
--- | --- |
| |
a ---- b ----
| | | |
---- ----
swap_one(p, q)從main()函式呼叫函式:
p (pointer) q (pointer)
--- ---
| |--- | |---
--- | --- |
| |
a ---- b ----
| | | |
---- ----
| |
| |
--- | --- |
| |--- | |---
--- ---
x (pointer) y (pointer)
pointing to a pointing to b
(x and y are parameters of swap_one())
執行這些swap_one()函式陳述句后:
tmp = x;
x = y;
y = tmp;
指標x將指向該指標y所指向的地址,而指標y將指向該指標x在swap_one()被呼叫時所指向的地址。
p (pointer) q (pointer)
--- ---
| |--- | |---
--- | --- |
| |
a ---- b ----
| | ----- | |
---- | ----
| |
--------|---------
--- | | ---
| |--- ---| |
--- ---
x (pointer) y (pointer)
pointing to b pointing to a
請注意,指標p和指標q仍然分別指向變數a和b。這就是為什么當swap_one()函式回傳時,變數的值a并b不會被換。
如果要交換變數的值,其地址作為引數傳遞給swap_one()函式而不是取消參考指標引數并替換該位置的值,即您應該在swap_one()函式中執行以下操作:
tmp = *x;
*x = *y;
*y = tmp;
通過這些更改,其地址傳遞給swap_one()函式的變數的值將被交換,因為現在您正在取消參考指標x(即*x)和指標y(即*y)并在該位置分配值。
現在,來到第二個代碼的這一部分。當element不是的情況下NULL
} else {
if (element->next == NULL) list->tail = new_element;
new_element->next = element->next;
element->next = new_element;
請注意,element指標是型別的ListElmt,是的,它也是list_ins_next()函式的區域指標變數。但是,這里我們利用這個區域指標變數來修改它所指向的結構成員的值。
new_element (pointer of type ListElmt)
----
| |-----
---- |
|
-----------
| | |
-----------
^ ^
| |
data next
pointer pointer
element (pointer of type ListElmt, which is pointing to an existing node of list
---- passed to list_ins_next() function)
| |-----
---- |
|
-----------
| | |
-----------
^ ^
| |
data next
pointer pointer
請注意,這
new_element->next
與
(*new_element).next
這意味著,取消參考new_element指標(轉到它指向的位置)并訪問該next位置的指標。
所以這
new_element->next = element->next;
將使new_element->next指標指向element->next指標所指的內容,這
element->next = new_element; // same as (*element).next = new_element;
將使element->next指標指向new_element指標所指向的內容。執行這些陳述句后,
new_element (pointer of type ListElmt)
----
| |-----
---- |
|
-----------
--- | | |-------> (pointing to what element->next was pointing at)
| -----------
| ^ ^
| | |
| data next
| pointer pointer
--------------------
|
element |
| |----- |
---- | |
| |
----------- |
| | |----
-----------
^ ^
| |
data next
pointer pointer
因此,如果要更改傳遞給函式的指標,則必須在呼叫函式中取消參考它。
如果您仍然感到困惑,請僅檢查以下內容:
在你的第二個代碼中,如果你做的和你在第一個代碼中做的一樣:
example = <some pointer of type ListElmt>;
即分配一些其他相同型別的指標給example,這就是會發生的事情:
element
---- -----------
| |---------------> | | |
---- -----------
(The original ListElmt type element
whose address passed to list_ins_next() function)
-----------
| | |
-----------
^ ^
| |
data next
pointer pointer
現在,當list_ins_next()函式回傳時,其地址傳遞給該函式的原始元素將保持不變。
額外的:
在這里,您的程式正在泄漏記憶體:
int *p = (int *) malloc(sizeof(int));
int *q = (int *) malloc(sizeof(int));
p = &a;
q = &b;
因為分配的記憶體的參考,對指標p和q(使用malloc())時,將要分配丟失&a,并&b以p和q分別。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/382567.html
上一篇:在C中搜索陣列
