在〈定义结构〉中示范的printAcct
函数,参数直接以结构类型定义,指定结构实例作为实参时,会创建新的实例并复制各个值域。
如果不希望复制的行为发生,可以传递地址,例如:
#include <stdio.h>
typedef const char* String;
typedef struct {
String id;
String name;
double balance;
} Account;
void deposit(Account *acct, double amount) {
if(amount <= 0) {
puts("必须存入正数");
return;
}
acct->balance += amount;
}
void withdraw(Account *acct, double amount) {
if(amount > acct->balance) {
puts("余额不足");
return;
}
acct->balance -= amount;
}
int main() {
Account acct = {"1234-5678", "Justin Lin", 1000};
deposit(&acct, 500);
withdraw(&acct, 200);
// 显示 Account(1234-5678, Justin Lin, 1300.000000)
printf("Account(%s, %s, %f)\n", acct.id, acct.name, acct.balance);
return 0;
}
如果使用结构定义的指针来访问成员,必须使用->
运算符,因为传递的是结构实例的地址,函数中对实例的变更,就是对原结构实例的变更。
以上范例的withdraw
、deposit
等函数,都是服务于Account
,若想要的话,也可以令函数成为结构的成员之一,这么组合有点面向对象语言中,对象与方法的概念,例如:
#include <stdio.h>
#include <stdlib.h>
typedef const char* String;
typedef struct Account {
String id;
String name;
double balance;
char *_to_str;
void (*deposit)(struct Account*, double);
void (*withdraw)(struct Account*, double);
String (*to_str)(struct Account*);
} Account;
void deposit(Account *acct, double amount) {
if(amount <= 0) {
puts("必须存入正数");
return;
}
acct->balance += amount;
}
void withdraw(Account *acct, double amount) {
if(amount > acct->balance) {
puts("余额不足");
return;
}
acct->balance -= amount;
}
String to_str(Account *acct) {
int n = snprintf(NULL, 0,
"Account(%s, %s, %f)",
acct->id, acct->name, acct->balance
);
if(acct->_to_str != NULL) {
free(acct->to_str);
}
acct->_to_str = malloc((n + 1) * sizeof(char));
snprintf(acct->_to_str, n + 1,
"Account(%s, %s, %f)",
acct->id, acct->name, acct->balance
);
return acct->_to_str;
}
Account* new_account(String id, String name, double balance) {
Account *acct = (Account*) malloc(sizeof(Account));
acct->id = id;
acct->name = name;
acct->balance = balance;
acct->_to_str = NULL;
acct->deposit = deposit;
acct->withdraw = withdraw;
acct->to_str = to_str;
return acct;
}
void del_account(Account *acct) {
free(acct->_to_str);
free(acct);
}
int main() {
Account *acct = new_account("1234-5678", "Justin Lin", 1000);
acct->deposit(acct, 500);
acct->withdraw(acct, 200);
printf("%s\n", acct->to_str(acct));
del_account(acct);
return 0;
}