[英]Can someone explain how memory is allocated to double pointer in the following code
[英]Can someone explain how pointer to pointer works?
我不太了解指針的工作原理。 有什么方法可以在不使用指針的情況下完成相同的工作?
struct customer
{
char name[20];
char surname[20];
int code;
float money;
};
typedef struct customer customer;
void inserts(customer **tmp)
{
*tmp = (customer *)malloc(sizeof(customer));
puts("Give me a customer name, surname code and money");
scanf("%s %s %d %f", (*tmp)->name, (*tmp)->surname, &(*tmp)->code, &(*tmp)->money);
}
指向指針的指針101
假設您有一個int
變量x
: int x;
。
printf("x's memory address = %p\\n", &x);
printf("x=%d\\n", x);
x = 42;
x
,則該函數無法操縱x
的值。 &x
的地址傳遞給函數( &x
),則該函數可以操縱&x
的值。 現在,假設您有一個指針變量p
,它假定它指向一個int
: int *p;
printf("p's memory addr = %p\\n", &p
printf("Address where `p` is pointing: %p\\n", p);
printf("int = %d\\n", *p);
p = &x
p = &x;
或p = NULL
p
),則該函數無法操縱“ p”來更改其指向的位置。 &p
),則該函數可以操縱`p`指向的內容。 現在,假設您有一個指向指針變量pp
的指針,假定它指向一個指向“ int”的指針: int **pp;
...或:void inserts(客戶** tmp ):
回到問題
否。假設以下內容:
void inserts(customer **tmp);
...
{
customer cust;
custPtr custPtr = &cust;
inserts(&custPtr);
...
inserts()
函數需要一個指針的地址才能操縱custPtr
指向的位置。
如果相反:
void inserts2(customer *tmp);
...
{
customer cust;
custPtr custPtr = &cust;
inserts2(custPtr);
...
insert2()
將獲得custPtr
值的副本,該值是cust
的地址。 因此, insert2()
可以修改cust
的值,但不能更改custPtr
指向的位置。
對於類型T
任何參數,如果要修改參數的值並使更改反映在調用方中,則必須傳遞一個指針:
void foo( T *ptr )
{
*ptr = new_value();
}
void bar( void )
{
T var;
foo( &var ); // writes to var
}
如果T
是一個指針類型Q *
,那么您將獲得一個指向該指針的指針:
void foo( Q **ptr )
{
*ptr = new_value();
}
void bar( void )
{
Q *var;
foo( &var ); // writes to var
}
您可以使用typedefs隱藏變量的指針,但是以我的經驗,將指針隱藏在typedefs后面是不好的做法。
您可以更改函數以返回指針值,而不是像@Namfuak建議的那樣寫入參數:
Q *foo( void )
{
Q *val = new_value();
return val;
}
void bar( void )
{
Q *var;
var = foo();
}
如果指針是您的電話簿條目,則可以認為指向該指針的指針是告訴您該條目所在的電話簿。
查看您的代碼:
struct customer {
char name[20];
char surname[20];
int code;
float money;
};
首先, 您不應將float類型用於money 。
您的問題與C FAQ 4.8有關 。 基本上,您具有插入客戶記錄的功能。 您想在哪里插入記錄? 很顯然,有記錄的東西,例如電話簿,數據庫等。因此,您需要的是指向某個東西的指針,該東西包含指向要插入的對象的指針。
現在,對於其余的代碼,首先請注意, 您不應該malloc
的返回值 。 其次, 使用scanf
是嚴重的安全風險 。 第三,您正在inserts
函數中分配新的客戶記錄,但是您無法將任何失敗傳達給調用函數的代碼。
可以說,函數的名稱應類似於create_customer_interactive
以表明它所做的不僅僅是在記錄列表中插入一條記錄。
這是代碼的結構方式:
#include <stdio.h>
#include <stdlib.h>
struct customer {
char *name;
char *surname;
int code;
int money; /* in cents */
};
typedef struct customer *PCustomer;
int read_customer_record(FILE *fp, PCustomer customer) {
/* dummy implementation */
customer->name = "A. Tester";
customer->surname = "McDonald";
customer->code = 123;
customer->money = 100 * 100;
return 1;
}
PCustomer insert_record_interactive(PCustomer *db, FILE *fp) {
PCustomer tmp = malloc(sizeof(*tmp));
if (!tmp) {
return NULL;
}
if (!read_customer_record(fp, tmp)) {
free(tmp);
return NULL;
}
*db = tmp;
return tmp;
}
int main(void) {
PCustomer new_customer;
PCustomer *db = malloc(3 * sizeof(*db));
if (!db) {
perror("Failed to allocate room for customer records");
exit(EXIT_FAILURE);
}
/* insert a record in the second slot */
new_customer = insert_record_interactive(&db[1], stdin);
if (!new_customer) {
perror("Failed to read customer record");
exit(EXIT_FAILURE);
}
printf(
"%s %s (%d) : $%.2f\n",
new_customer->name,
new_customer->surname,
new_customer->code,
((double)new_customer->money) / 100.0
);
return 0;
}
多個間接級別可能導致混亂。 一個好的策略是通過減少間接級別來減少混亂。
除了使用scanf()
之外,還有其他合法的問題,以下是實現此目的的一種方法:
void inserts(customer **tmp)
{
customer *new_cust = malloc(sizeof *new_cust);
if ( !new_cust ) {
fprintf(stderr, "Couldn't allocate memory.\n");
exit(EXIT_FAILURE);
}
puts("Give me a customer name, surname code and money");
scanf("%s %s %d %f", new_cust->name, new_cust->surname,
new_cust->code, new_cust->money);
/* We delay using multiple levels of indirection
until we get to the very last line, here. */
*tmp = new_cust;
}
正如其他人提到的那樣,在這種特殊情況下,僅返回指針可能會更容易。
void inserts(customer *tmp[])
{
*tmp = malloc(sizeof(customer));
puts("Give me a customer name, surname code and money");
scanf("%s %s %d %f", (*tmp)->name, (*tmp)->surname, &(*tmp)->code, &(*tmp)->money);
}
那是等效的。 指向指針的指針也可以表示為指向未知大小數組的指針。
發生的是,* tmp被分配給類型為“ customer”的1個元素的數組。 tmp本身以兩種方式(** tmp和* tmp [])都指向未知大小的“客戶”元素數組的指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.