结构与指针


在〈定义结构〉中示范的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; 
}

如果使用结构定义的指针来访问成员,必须使用->运算符,因为传递的是结构实例的地址,函数中对实例的变更,就是对原结构实例的变更。

以上范例的withdrawdeposit等函数,都是服务于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; 
}




展开阅读全文