函数指针 #
一、函数指针基础 #
1.1 函数指针类型 #
使用 *const fn 定义函数指针类型:
zig
const std = @import("std");
const BinaryOp = *const fn (i32, i32) i32;
fn add(a: i32, b: i32) i32 {
return a + b;
}
fn subtract(a: i32, b: i32) i32 {
return a - b;
}
pub fn main() void {
const op: BinaryOp = add;
std.debug.print("add(10, 5) = {}\n", .{op(10, 5)});
const op2: BinaryOp = subtract;
std.debug.print("subtract(10, 5) = {}\n", .{op2(10, 5)});
}
1.2 函数指针作为参数 #
zig
const std = @import("std");
const CompareFn = *const fn (i32, i32) bool;
fn lessThan(a: i32, b: i32) bool {
return a < b;
}
fn greaterThan(a: i32, b: i32) bool {
return a > b;
}
fn findExtreme(arr: []const i32, compare: CompareFn) ?i32 {
if (arr.len == 0) return null;
var extreme = arr[0];
for (arr[1..]) |item| {
if (compare(item, extreme)) {
extreme = item;
}
}
return extreme;
}
pub fn main() void {
const numbers = [_]i32{ 3, 7, 2, 9, 1, 5 };
const min = findExtreme(&numbers, lessThan);
const max = findExtreme(&numbers, greaterThan);
std.debug.print("Min: {}, Max: {}\n", .{ min.?, max.? });
}
1.3 函数指针数组 #
zig
const std = @import("std");
const Operation = *const fn (i32, i32) i32;
fn add(a: i32, b: i32) i32 { return a + b; }
fn subtract(a: i32, b: i32) i32 { return a - b; }
fn multiply(a: i32, b: i32) i32 { return a * b; }
fn divide(a: i32, b: i32) i32 { return @divTrunc(a, b); }
pub fn main() void {
const operations = [_]Operation{ add, subtract, multiply, divide };
const names = [_][]const u8{ "add", "subtract", "multiply", "divide" };
const a: i32 = 10;
const b: i32 = 3;
for (operations, names) |op, name| {
std.debug.print("{s}({}, {}) = {}\n", .{ name, a, b, op(a, b) });
}
}
二、回调函数 #
2.1 基本回调 #
zig
const std = @import("std");
const Callback = *const fn (i32) void;
fn processNumbers(arr: []const i32, callback: Callback) void {
for (arr) |item| {
callback(item);
}
}
fn printNumber(n: i32) void {
std.debug.print("{} ", .{n});
}
fn printSquare(n: i32) void {
std.debug.print("{} ", .{n * n});
}
pub fn main() void {
const numbers = [_]i32{ 1, 2, 3, 4, 5 };
std.debug.print("Numbers: ", .{});
processNumbers(&numbers, printNumber);
std.debug.print("\n", .{});
std.debug.print("Squares: ", .{});
processNumbers(&numbers, printSquare);
std.debug.print("\n", .{});
}
2.2 带上下文的回调 #
zig
const std = @import("std");
const Context = struct {
sum: i32,
count: usize,
};
const CallbackWithContext = *const fn (*Context, i32) void;
fn accumulate(ctx: *Context, value: i32) void {
ctx.sum += value;
ctx.count += 1;
}
fn processWithContext(arr: []const i32, ctx: *Context, callback: CallbackWithContext) void {
for (arr) |item| {
callback(ctx, item);
}
}
pub fn main() void {
const numbers = [_]i32{ 1, 2, 3, 4, 5 };
var ctx = Context{ .sum = 0, .count = 0 };
processWithContext(&numbers, &ctx, accumulate);
std.debug.print("Sum: {}, Count: {}, Average: {d}\n", .{
ctx.sum,
ctx.count,
@as(f64, @floatFromInt(ctx.sum)) / @as(f64, @floatFromInt(ctx.count)),
});
}
2.3 事件处理 #
zig
const std = @import("std");
const EventHandler = *const fn ([]const u8) void;
const EventEmitter = struct {
handlers: [10]?EventHandler,
count: usize,
fn init() EventEmitter {
return .{
.handlers = [_]?EventHandler{null} ** 10,
.count = 0,
};
}
fn on(self: *EventEmitter, handler: EventHandler) void {
if (self.count < self.handlers.len) {
self.handlers[self.count] = handler;
self.count += 1;
}
}
fn emit(self: EventEmitter, event: []const u8) void {
for (self.handlers[0..self.count]) |handler| {
if (handler) |h| {
h(event);
}
}
}
};
fn logHandler(event: []const u8) void {
std.debug.print("Log: {s}\n", .{event});
}
fn alertHandler(event: []const u8) void {
std.debug.print("Alert: {s}\n", .{event});
}
pub fn main() void {
var emitter = EventEmitter.init();
emitter.on(logHandler);
emitter.on(alertHandler);
emitter.emit("User logged in");
emitter.emit("File uploaded");
}
三、高阶函数 #
3.1 map 函数 #
zig
const std = @import("std");
fn map(arr: []const i32, transform: *const fn (i32) i32, result: []i32) void {
for (arr, result) |item, *r| {
r.* = transform(item);
}
}
fn double(x: i32) i32 { return x * 2; }
fn square(x: i32) i32 { return x * x; }
fn negate(x: i32) i32 { return -x; }
pub fn main() void {
const numbers = [_]i32{ 1, 2, 3, 4, 5 };
var result: [5]i32 = undefined;
map(&numbers, double, &result);
std.debug.print("Doubled: {any}\n", .{result});
map(&numbers, square, &result);
std.debug.print("Squared: {any}\n", .{result});
map(&numbers, negate, &result);
std.debug.print("Negated: {any}\n", .{result});
}
3.2 filter 函数 #
zig
const std = @import("std");
const Predicate = *const fn (i32) bool;
fn filter(arr: []const i32, predicate: Predicate, result: []i32) usize {
var count: usize = 0;
for (arr) |item| {
if (predicate(item)) {
result[count] = item;
count += 1;
}
}
return count;
}
fn isEven(x: i32) bool { return x % 2 == 0; }
fn isPositive(x: i32) bool { return x > 0; }
fn isGreaterThan3(x: i32) bool { return x > 3; }
pub fn main() void {
const numbers = [_]i32{ -2, -1, 0, 1, 2, 3, 4, 5 };
var result: [8]i32 = undefined;
const even_count = filter(&numbers, isEven, &result);
std.debug.print("Even: {any}\n", .{result[0..even_count]});
const positive_count = filter(&numbers, isPositive, &result);
std.debug.print("Positive: {any}\n", .{result[0..positive_count]});
const gt3_count = filter(&numbers, isGreaterThan3, &result);
std.debug.print("> 3: {any}\n", .{result[0..gt3_count]});
}
3.3 reduce 函数 #
zig
const std = @import("std");
const Reducer = *const fn (i32, i32) i32;
fn reduce(arr: []const i32, initial: i32, reducer: Reducer) i32 {
var acc = initial;
for (arr) |item| {
acc = reducer(acc, item);
}
return acc;
}
fn add(a: i32, b: i32) i32 { return a + b; }
fn multiply(a: i32, b: i32) i32 { return a * b; }
fn max(a: i32, b: i32) i32 { return if (a > b) a else b; }
fn min(a: i32, b: i32) i32 { return if (a < b) a else b; }
pub fn main() void {
const numbers = [_]i32{ 1, 2, 3, 4, 5 };
std.debug.print("Sum: {}\n", .{reduce(&numbers, 0, add)});
std.debug.print("Product: {}\n", .{reduce(&numbers, 1, multiply)});
std.debug.print("Max: {}\n", .{reduce(&numbers, numbers[0], max)});
std.debug.print("Min: {}\n", .{reduce(&numbers, numbers[0], min)});
}
四、实战示例 #
4.1 排序器 #
zig
const std = @import("std");
const CompareFn = *const fn (i32, i32) bool;
fn sort(arr: []i32, compare: CompareFn) void {
var i: usize = arr.len;
while (i > 1) : (i -= 1) {
for (arr[0 .. i - 1], 0..) |*item, j| {
if (compare(arr[j + 1], item.*)) {
const temp = item.*;
item.* = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
pub fn main() void {
var numbers = [_]i32{ 5, 2, 8, 1, 9, 3, 7, 4, 6 };
var ascending = numbers;
sort(&ascending, struct {
fn cmp(a: i32, b: i32) bool {
return a < b;
}
}.cmp);
std.debug.print("Ascending: {any}\n", .{ascending});
var descending = numbers;
sort(&descending, struct {
fn cmp(a: i32, b: i32) bool {
return a > b;
}
}.cmp);
std.debug.print("Descending: {any}\n", .{descending});
}
4.2 命令模式 #
zig
const std = @import("std");
const Command = *const fn () void;
const CommandQueue = struct {
commands: [10]?Command,
count: usize,
fn init() CommandQueue {
return .{
.commands = [_]?Command{null} ** 10,
.count = 0,
};
}
fn add(self: *CommandQueue, cmd: Command) void {
if (self.count < self.commands.len) {
self.commands[self.count] = cmd;
self.count += 1;
}
}
fn execute(self: CommandQueue) void {
for (self.commands[0..self.count]) |cmd| {
if (cmd) |c| {
c();
}
}
}
};
fn sayHello() void {
std.debug.print("Hello!\n", .{});
}
fn sayGoodbye() void {
std.debug.print("Goodbye!\n", .{});
}
fn sayThanks() void {
std.debug.print("Thanks!\n", .{});
}
pub fn main() void {
var queue = CommandQueue.init();
queue.add(sayHello);
queue.add(sayThanks);
queue.add(sayGoodbye);
queue.execute();
}
五、总结 #
函数指针要点:
| 特性 | 说明 |
|---|---|
| 函数指针类型 | *const fn(args) T |
| 回调函数 | 函数指针作为参数 |
| 高阶函数 | 接受或返回函数 |
| 上下文 | 使用结构体传递状态 |
下一步,让我们学习结构体!
最后更新:2026-03-27