将经过默认参数提升的对象传递给“va_start”
Posted
技术标签:
【中文标题】将经过默认参数提升的对象传递给“va_start”【英文标题】:Passing an object that undergoes default argument promotion to 'va_start' 【发布时间】:2019-10-09 09:09:23 【问题描述】:这是我的第一个 Xcode 应用程序和 Objective-c,所以请给我一些放松 :)
我尝试在谷歌上搜索该问题,但我看不到有关 Xcode 和应用程序开发的任何帮助。我在 //
之后添加了错误按摩- (id)initWithBytes:(int8_t)byte1, ... //Error: 1. Parameter of type 'int8_t' (aka 'signed char') is declared here
va_list args;
va_start(args, byte1); //Error: Passing an object that undergoes default argument promotion to 'va_start' has undefined behavior
unsigned int length = 0;
for (int8_t byte = byte1; byte != -1; byte = va_arg(args, int))
length++;
va_end(args);
if ((self = [self initWithLength:length]) && (length > 0))
va_list args;
va_start(args, byte1); // Error: Passing an object that undergoes default argument promotion to 'va_start' has undefined behavior
int i = 0;
for (int8_t byte = byte1; byte != -1; byte = va_arg(args, int))
_array[i++] = byte;
va_end(args);
return self;
提前谢谢你!!
【问题讨论】:
哇,这很复杂。为什么不传递uint8_t
s 和长度的数组?
@***foe 希望我知道如何 :) 我太新了,无法理解我的代码的作用。
很少使用可变参数。您通常只会看到它们用于记录/打印(请参阅 NSLog()
和 printf()
),所以请扔掉它们。如果你想传递一个字符/字节数组,那么传递一个指针和一个长度,这足以描述数组。例如:- (nonnull instancetype)initWithBuffer:(const uint_t *)buffer ofLength:(NSUInteger)length ... ;
。事实上,这几乎就是 NSData
类所做的事情,所以你可能应该改用它。显示类声明,我会提供正确的答案。
我不知道为什么va_start
不喜欢int8_t
,尝试使用其他类型。顺便说一句,你想达到什么目的?
我尝试了int8_t
的几个选项,但仍然出现错误。你建议我用哪一个? @Cy-4AH
【参考方案1】:
va_start()
将指向传递给函数的第一个参数的指针保存到va_list
中。
参数本身通过硬件堆栈传递。
int8_t 的问题来自于硬件堆栈的实现方式。 (至少在 x86 中)
就像 SSE 和 MMX 一样,堆栈要求存储在其上的元素对齐等于 16 位的倍数,因此传递给函数的所有内容都将具有至少 16 位大小,无论其类型如何。
但问题是va_arg()
不知道这一切。从历史上看,它是一个宏,它所做的只是返回一个存储在va_list
中的指针,并将va_list
递增sizeof(type)
。
因此,当您检索下一个参数时,返回的指针不指向下一个参数,而是指向它之前的一个字节 - 取决于 va_arg
是宏还是编译器内置函数。
这就是警告的含义。
至少是国际海事组织。请原谅我的英语,这是我的第二语言。
【讨论】:
我对objective-C一无所知,但这个答案对我来说是正确的。以下是支持这一点的 C/C++ 中一些更详细的示例。 wiki.sei.cmu.edu/confluence/display/cplusplus/…以上是关于将经过默认参数提升的对象传递给“va_start”的主要内容,如果未能解决你的问题,请参考以下文章