【问题标题】:Why does the compiler complain about my simple function call?为什么编译器会抱怨我的简单函数调用?
【发布时间】:2012-11-14 16:39:12
【问题描述】:

刚从 Java 背景学习 Objective-C。我正在尝试编写一个除了教我如何用这种语言编写函数之外没有其他目的的程序,而且我到处都遇到错误。问题是因为我昨天刚开始使用这种语言,所以这些错误对我来说毫无意义。这是我目前所拥有的。

主要方法:

int main (int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSString * prompt = @"Hello World";

        prompt = writePromptMessage(prompt);

        NSLog(@"%@", prompt);
    }

    return 0;
}

特殊方法:

NSString *writePromptMessage(NSString * prompt)
{
    return prompt;
}

我的错误:

  • 函数 writePromptMessage 的隐式声明在 C99 中无效
  • ARC 不允许将“int”隐式转换为“NSString *”
  • 从 int 分配 NSString strong 的不完整整数到指针转换
  • writePromptMessage 的类型冲突

【问题讨论】:

  • 你的函数需要在main之前声明。

标签: objective-c


【解决方案1】:

与 Java 不同,您需要在使用它之前添加一个函数声明(又名函数原型)。函数声明就像函数定义一样,但没有函数体(即代码),并以分号结尾:

// This is a function declaration:
NSString *writePromptMessage(NSString * prompt);

// This is a function definition:
NSString *writePromptMessage(NSString * prompt)
{
    // Function body goes here
}

为了能够调用一个函数,你需要在之前写一个声明使用站点:

NSString *writePromptMessage(NSString * prompt);  // declaration

int main (int argc, const char * argv[])
{
    ...
    writePromptMessage(...);  // usage
}

// definition follows

或者,您可以将整个定义放在使用站点之前,但这并不总是可行的(例如,如果您有两个可以相互调用的函数)。

C 和 Objective-C 确实允许您调用没有可见声明的函数,但这被认为是已弃用的功能,因为它很容易被误用并导致细微的错误:

如果在没有可见声明的情况下调用函数,编译器会创建一个 隐式 声明

  • 隐式声明采用任意数量和类型的参数
  • 隐式声明返回int

所以,发生的事情是编译器假设writePromptMessage 在它第一次看到它时返回int,这是错误的,并且会导致一连串其他错误。对于不返回 int 的函数,您必须永远不要使用隐式函数声明,而对于确实返回 int 的函数,您应该永远不要使用隐式函数声明.

【讨论】:

  • 所以基本上我需要先对我将在 main 中使用的所有方法进行我的声明。然后写我的main方法。然后写我的方法体?
【解决方案2】:

您要么需要在main 之前添加一个函数声明,要么在那里定义整个函数。例如,编译:

#import <Foundation/Foundation.h>

void hello(NSString *text) {
    NSLog(@"%@", text);
}

int main(int argc, const char * argv[])
{
   @autoreleasepool {
        hello(@"Foo");
    }
    return 0;
}

这也是如此:

#import <Foundation/Foundation.h>

void hello(NSString*);

int main(int argc, const char * argv[])
{
   @autoreleasepool {
        hello(@"Foo");
    }
    return 0;
}

void hello(NSString *text) {
    NSLog(@"%@", text);
}

编译器会自动注意到Objective-C的方法 (that’s a different thing),所以不需要提前声明;这编译得很好:

@interface Foo : NSObject
@end

@implementation Foo

- (void) doA
{
    [self doB];
}

- (void) doB
{}

@end

显然编译器对常规 C 函数没有这么聪明,可能是为了符合 C 语言规范。

【讨论】:

    【解决方案3】:

    所有这些错误很可能源于同一个问题。看来您还没有声明或定义 writePromptMessage 之前 你的 main 方法。在 C(和 Objective-C)中,您必须在使用函数之前声明或定义函数。编译器对writePromptMessage 一无所知,从而导致您的错误消息。

    函数 writePromptMessage 的隐式声明在 C99 中无效

    表示你还没有声明writePromptMessage,所以...

    ARC 不允许将“int”隐式转换为“NSString *”

    在 C 语言中,函数默认返回 int;由于您尚未声明 writePromptMessage,编译器假定它是一个返回 int 的函数,不应将其转换为 NSString *

    从 int 分配 NSString strong 的不完整整数到指针转换

    见上文(基本上是同一个问题)。

    writePromptMessage 的冲突类型

    哦!现在编译器已经看到了writePromptMessage...但是等等。它已经假定writePromptMessage 返回了int,现在它看到它返回了NSString,从而导致错误。


    如果你把writePromptMessage的定义放在之前main,或者至少声明它的原型,à la:

    NSString *writePromptMessage(NSString * prompt);
    

    之前 main,你应该没事的。

    【讨论】:

      猜你喜欢
      • 2012-09-12
      • 2019-06-16
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 2016-11-01
      相关资源
      最近更新 更多