我可以在传递 va_list 之前对其进行修改吗?

发布于 2024-12-07 12:44:58 字数 942 浏览 0 评论 0原文

在我试图理解(Objective-)C 中的 va_list 能做什么和不能做什么时,我遇到了这个小难题。我希望在 NSString 上创建一个类别,在某些情况下可以稍微简化 stringWithFormat: 消息,只是为了好玩。我的目标是能够使用这样的实现:

[@"My %@ format %@!" formattedWith:@"super", @"rocks"];

希望最终得到一个字符串“My super formatrocks!”。我的(不正确的)方法实现如下所示:

- (NSString *)formattedWith:(NSString *)arguments, ...
{
    va_list list;
    va_start(list, arguments);
    NSString *formatted = [[[NSString alloc] initWithFormat:self arguments:list] autorelease];
    va_end(list);
    return formatted;
}

现在的问题是,一旦调用 va_start() , va_list 就会“缩短”(因为缺少更好的词)并且只包含其余部分参数(在示例中仅保留 @"rocks" ,加上我不关心的调用对象)。因此,传递到 initWithFormat: 消息的内容会呈现错误类型的结果。

继续提问。在将 va_list 传递给 initWithFormat: 消息之前,有没有办法修改 va_list,以便我可以以某种方式将第一个参数移回到列表中?

我并不是在寻找一个迭代过程,我自己循环遍历 va_list,我希望了解 va_list 的整体局限性。谢谢!

In my attempts to understand what I can and can't do with a va_list in (Objective-)C, I came across this little puzzle. I was hoping to create a category on NSString that would simplify the stringWithFormat: message a bit in some cases, just for the fun of it. What I was aiming for was being able to use the implementation like this:

[@"My %@ format %@!" formattedWith:@"super", @"rocks"];

Hoping to end up with a string saying "My super format rocks!". My (incorrect) method implementation looks like this:

- (NSString *)formattedWith:(NSString *)arguments, ...
{
    va_list list;
    va_start(list, arguments);
    NSString *formatted = [[[NSString alloc] initWithFormat:self arguments:list] autorelease];
    va_end(list);
    return formatted;
}

Now the problem is that as soon as va_start() is called, the va_list is 'shortened' (for lack of a better word) and only contains the rest of the arguments (in the case of the example only @"rocks" remains, plus the calling object which I don't care about). What's passed onto the initWithFormat: message therefore renders the wrong kind of result.

On to the question. Are there ways to modify the va_list before I pass it to the initWithFormat: message, so I can somehow shift the first argument back onto the list?

I'm not looking for an iterative process where I loop through the va_list myself, I'm looking to understand the limits of va_list as a whole. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独孤求败 2024-12-14 12:44:58

va_list 无法安全修改。 va_start 参数还需要一个参数来启动被排除的列表。解决此问题的方法是传递额外的无用参数或使用可变参数宏。

//Method declaration
-(NSString*)formattedWith:(NSString*)ignored,...;

//Opt 1 (pass anything for first value)
[@"My %@ format %@!" formattedWith:nil, @"super", @"rocks"];

//Opt 2 (create a macro for the arguments)
#define VA_OPT(...) nil, ##__VA_ARGS__ //VARIADIC OPTIONAL
[@"My %@ format %@!" formattedWith:VA_OPT(@"super", @"rocks"];

//Opt 3 (just create a macro for the whole string format)
//Obviously you should just use the NSString method directly before resorting to this
#define FORMATTED_NSSTRING(str, ...) [NSString stringWithFormat:str, ##__VA_ARGS__]
FORMATTED_NSSTRING(@"My %@ format %@!", @"super", @"rocks")

The va_list can not be modified safely. The va_start argument also requires an argument to start the list which is excluded. The ways to work around this are to either pass an additional useless argument or use variadic macros.

//Method declaration
-(NSString*)formattedWith:(NSString*)ignored,...;

//Opt 1 (pass anything for first value)
[@"My %@ format %@!" formattedWith:nil, @"super", @"rocks"];

//Opt 2 (create a macro for the arguments)
#define VA_OPT(...) nil, ##__VA_ARGS__ //VARIADIC OPTIONAL
[@"My %@ format %@!" formattedWith:VA_OPT(@"super", @"rocks"];

//Opt 3 (just create a macro for the whole string format)
//Obviously you should just use the NSString method directly before resorting to this
#define FORMATTED_NSSTRING(str, ...) [NSString stringWithFormat:str, ##__VA_ARGS__]
FORMATTED_NSSTRING(@"My %@ format %@!", @"super", @"rocks")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文