【问题标题】:Read only variable is not assignable只读变量不可赋值
【发布时间】:2020-05-08 10:41:08
【问题描述】:

我认为这是后来的 Xcode 问题(我使用的是 Xcode 11),因为此代码以前在旧版本中很好。

在我的main.mm 文件中,我有以下内容;

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSString * path = [[NSBundle mainBundle] pathForResource:  @"fd" ofType: @"dat"];
    NSData* image = [NSData dataWithContentsOfFile:path];

    const char* szPathName = [path UTF8String];
    const char* pos = strrchr (szPathName, '/');
    //char* pos = strrchr (szPathName, '/');


    *pos = 0;

    if (CreateFaceFatted(szPathName) == 0)
    {
        NSLog(@"Init Dictionary failed");
    }
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

我已将char* pos = strrchr (szPathName, '/'); 更改为const char* pos = strrchr (szPathName, '/');,否则它会抛出一个

Cannot initialize a variable of type 'char *' with an rvalue of type 'const char *'

所以通过改用 const char,我至少可以继续进行,但是在以下部分;

*pos = 0;

我收到一个错误Read only variable is not assignable

我对与 obj-c 混合的 c++ 代码有一点了解,但我正在努力想办法让它编译

【问题讨论】:

  • C++ 标准库中有两个std::strrchr 重载:一个采用const char* 第一个参数并返回一个const char* 结果,另一个采用char * 参数并返回一个char * 结果。由于szPathName 的常量性,您使用的是前者。要使用后者,szPathName 需要是非常量的。

标签: c++ ios objective-c xcode


【解决方案1】:

您将指针 szPathName 声明为指向常量数据的指针

 const char* szPathName = [path UTF8String];

所以你不能使用指针pos改变指向的数据

*pos = 0;

也应使用限定符 const 声明,因为函数 strchr 返回一个常量指针。

const char* pos = strrchr (szPathName, '/');

使指针 szPathName 指向非常量数据。

【讨论】:

  • 抱歉,我在这里展示了我的 c++ 新手,我该如何指出非常量数据?
  • @user1695971 您需要声明不带限定符 const 的指针 szPathName,并且该指针应指向一个非常量字符数组。例如,您可能不会更改字符串文字。
  • 嗯我已经尝试过了,但是在删除 const 限定符时遇到了一个新错误Cannot initialize a variable of type 'char *' with an rvalue of type 'const char * _Nullable'...
【解决方案2】:

自从你的previous question 之后,你似乎什么都没做,所以确实需要你付出一些努力。

让我们逐步检查您的原始代码,希望有助于理解问题:

我认为这是后来的 Xcode 问题(我正在使用 Xcode 11),因为此代码以前在旧版本中很好。

这不是 Xcode 问题本身,你的代码总是错误的,但幸运的是你产生了想要的结果,只是错误和警告消息得到了改进。

const char* szPathName = [path UTF8String];

这一行接受path 引用的NSString 值,在其上调用UTF8String 方法,该方法返回一个指向C 字符串值的指针,并将该引用存储在szPathName 中。从 Objective-C 你会知道NSString 的值是不可变的,你不能改变字符串中的字符。 UTF8String 方法返回一个指向常量 C 字符串值的指针,因此 szPathName 的类型为 const char * - NSStringconst char * 分别是 Objective-C 和 C 中存储对常量的引用的变量的类型字符串;同样NSMutableStringchar * 是可变字符串引用的类型。

char* pos = strrchr (szPathName, '/');

这行代码在 C 字符串中搜索最右边的/ 并返回一个指向它的指针。正如您从 C++ 中的 last question strrchr() 中发现的那样,如果传递了 const char *,则返回 const char *。这行代码总是错误的,但似乎早期的编译器没有报告错误,即键入 pos 作为指向 mutable 字符串的指针,但它不是。正如在 Objective-C 中将 NSString * 值分配给 NSMutableString * 类型变量不会使引用的字符串可变,在 C 中将 const char * 值分配给 char * 类型变量不会使引用 C 字符串可变.

*pos = 0;

这一行是正确的,因为 pos 的类型是 char *,但也不正确,因为存储在 pos 中的值恰好是指向不可变 C 字符串的指针。

您的代码以前工作过,因为 C 在可变性/不可变性方面是松懈的,幸运的是,将 NSString 的实例写入一个 C 字符串存储在中(参见 UTF8String 文档)没有不会造成任何问题。

你不会解决你的问题,而是在不同的地方添加或删除const,这样做可能会导致代码看起来可以工作,但它可能随时容易中断。

正如您在上一个问题中向您建议的那样,不要尝试一次修复一行 C 代码,特别是考虑到您声明缺乏 C(++) 知识,您最好看看这段代码是什么尝试在 Objective-C 中尽可能多地编写代码。

那么代码的目的是什么?

  1. 从存储在path 中的文件的路径开始,作为NSString
  2. 确定该文件的父文件夹/目录
  3. 将该父文件夹作为常量 C 字符串值传递给函数 CreateFaceFatted

您已经有了获取文件路径并将其存储在path 中的代码,因此步骤 1 不需要任何工作。

您还知道如何从 NSString 值生成指向常量 C 字符串的指针 - 使用 UTF8String。至此,步骤 3 已涵盖。

剩下第 2 步。您当前的代码在转换为 C 字符串后尝试执行此操作,但您不知道该怎么做。但是您确实知道 Objective-C,NSString 上是否有一个方法/属性,它采用文件路径并返回包含文件夹/目录的路径? documentation 是一个值得一看的好地方。

希望这将帮助您了解您的问题,从而帮助您快速找到解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多