Ios 为什么只有在选择x86“U 64模拟器”时才会出现Complie错误;无法引用块内具有数组类型的声明";
我的问题是:为啥仅在使用 x86_64编译时会出现此编译错误?以及如何解决?Ios 为什么只有在选择x86“U 64模拟器”时才会出现Complie错误;无法引用块内具有数组类型的声明";,ios,objective-c,iphone,xcode,block,Ios,Objective C,Iphone,Xcode,Block,我的问题是:为啥仅在使用 x86_64编译时会出现此编译错误?以及如何解决? 我的问题是:为什么只有当select x86_64模拟器编译错误发生时才发生?如何解决 环境: Xcode v8.3.2 测试代码: + (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ... { va_list args; va_start(args, key); __block BOOL isOK = NO;
我的问题是:为什么只有当select x86_64模拟器编译错误发生时才发生?如何解决 环境: Xcode v8.3.2
测试代码:
+ (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ...
{
va_list args;
va_start(args, key);
__block BOOL isOK = NO;
[_queue inDatabase:^(FMDatabase *_dataBase)//
{
isOK = [_dataBase executeUpdate:sql withVAList:args];
}];
va_end(args);
return isOK;
}
不同的编译方式,编译错误情况:
- 【编译正常√】选择 通用iOS设备编译(建造)时:【armv7+arm64】
CompileC Test.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler CompileC Test.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
- 【编译正常√】 选择真机: iPhone4(7.1.2)编译(建造)时:【armv7】
CompileC Test.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
- 【编译错误×】选择模拟器: iphone5s(10.3)、iphonese(10.3)、iphone7plus(10.3)编译(建造)时:【x86_64】
复杂错误:CompileC Test.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
无法引用块内具有数组类型的声明 - 【编译正常√】选择模拟器: iphone5(10.3)编译(建造)时:【i386】
CompileC Test.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
- (FMResultSet *)executeQuery:(NSString*)sql, ... {
va_list args;
va_start(args, sql);
id result = [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args];
va_end(args);
return result;
}
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {
//xxx
}
经过尝试【有效的】解决方案(代码): 参考代码(灵感来源): FMDB类库里的 行刑函数
- (FMResultSet *)executeQuery:(NSString*)sql, ... {
va_list args;
va_start(args, sql);
id result = [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args];
va_end(args);
return result;
}
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {
//xxx
}
如果一个块捕获了一个非\u块变量,则在块中创建并存储该块时,会生成该变量的副本。数组不能用C赋值,这可能就是块的设计者不允许在块中捕获数组类型的变量的原因 什么类型的
va_list
不是由C标准指定的;它是特定于实现的。它可以实现为数组类型、指针类型、结构类型或其他类型,在同一编译器上的不同体系结构中,这可能是不同的。他们可能在x86_64中实现为数组类型,也可能实现为一些非数组类型在其他3种体系结构上。这没有什么不寻常的。你不能假设什么类型的va_list
在您的回答中,您定义了另一个函数并将va_list
传递给它,在va_list
是一个数组类型的情况下,这恰好起作用,因为C会自动将“T的数组”类型的任何参数调整为“指向T的指针”,因此方法+foo:key:withVAList:
中的参数args
实际上有一个指针类型,而va_list
是数组类型(与+foo:key:
方法中的args
不同),指针变量可以捕获到块中
另一种解决方案是获取va_列表
的地址,获取va_列表*
,并将其放入块中使用的变量中。无论va_列表
是什么,这都保证是指针类型,并且可以在块中很好地捕获。当您需要在中使用实际的va_列表
时在块的一侧,可以取消对指针的引用。例如,类似以下内容:
+ (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ...
{
va_list args;
va_start(args, key);
va_list *ptrToArgs = &args;
__block BOOL isOK = NO;
[_queue inDatabase:^(FMDatabase *_dataBase)
{
isOK = [_dataBase executeUpdate:sql withVAList:*ptrToArgs];
}];
va_end(args);
return isOK;
}
如果一个块捕获了一个非\u块变量,则在块中创建并存储该块时,会生成该变量的副本。数组不能用C赋值,这可能就是块的设计者不允许在块中捕获数组类型的变量的原因 什么类型的
va_list
不是由C标准指定的;它是特定于实现的。它可以实现为数组类型、指针类型、结构类型或其他类型,在同一编译器上的不同体系结构中,这可能是不同的。他们可能在x86_64中实现为数组类型,也可能实现为一些非数组类型在其他3种体系结构上。这没有什么不寻常的。你不能假设什么类型的va_list
在您的回答中,您定义了另一个函数并将va_list
传递给它,在va_list
是一个数组类型的情况下,这恰好起作用,因为C会自动将“T的数组”类型的任何参数调整为“指向T的指针”,因此方法+foo:key:withVAList:
中的参数args
实际上有一个指针类型,而va_list
是数组类型(与+foo:key:
方法中的args
不同),指针变量可以捕获到块中
另一种解决方案是获取va_列表
的地址,获取va_列表*
,并将其放入块中使用的变量中。无论va_列表
是什么,这都保证是指针类型,并且可以在块中很好地捕获。当您需要在中使用实际的va_列表
时在块的一侧,可以取消对指针的引用。例如,类似以下内容:
+ (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ...
{
va_list args;
va_start(args, key);
va_list *ptrToArgs = &args;
__block BOOL isOK = NO;
[_queue inDatabase:^(FMDatabase *_dataBase)
{
isOK = [_dataBase executeUpdate:sql withVAList:*ptrToArgs];
}];
va_end(args);
return isOK;
}