【问题标题】:cannot convert char* to int* in assignment c++ [closed]无法在赋值c ++中将char *转换为int * [关闭]
【发布时间】:2018-12-16 10:36:28
【问题描述】:

C++ 在表达式中将 char 隐式转换为 int(比 char 更大的数据类型),这意味着以下运行不会出现编译时错误:

char a = 'a';
int b = a;
cout << b << endl;
// output 
97

为什么下面会抛出编译时错误:

char a = 'a';
char* str = &a;
int* ptr;
ptr = str;

由于指针的大小是固定的(取决于 32/64 位操作系统),无论它们指向的数据类型如何,请帮助我理解为什么这种转换是非法的。

【问题讨论】:

  • 指针仍然具有强类型语义,这就是为什么在 c++ 中不允许这样做。
  • 您在这里做了一个隐含的假设,C++ 标准本身无法保证。也不太可能很快得到保证。除此之外,指针大小并不是唯一需要牢记的考虑因素。
  • 当编译器试图通过int* 写入4 字节时会发生什么情况?

标签: c++ pointers casting


【解决方案1】:

"由于指针的大小是固定的" 问题不是指针的大小,而是指向的类型,char 不是 int ,所以 char * 不是 int *

如果您在*str = &lt;value&gt; 之后执行所有操作,则一切正常,因为您只更改了一个字节,但*ptr = &lt;value&gt; 将写入多个字节,导致意外后果等

【讨论】:

  • 这是我无法理解的。在数据类型的隐式类型转换中,即使那时 char 也不是 int,那么隐式类型转换为什么/如何工作?
  • "char is not an int" 虽然您可以将char 隐式转换为int,但也许这就是OP 混乱的根源。
  • @HimanshuGupta 再次,这不是因为 char 成为 int 没有问题,它与指向 char 的指针相同
【解决方案2】:

你想做的是未定义的行为。

您从char 开始并获得指向它的指针。没关系。例如,指针可以是0x01。然后你说,实际上是指向 1 个字节的指针,让我们让它指向一个指向 4 个字节的指针(int 的假设为 32 位)。

显然,这是行不通的。其他 3 个字节来自哪里?

然后,假设它确实有效。您会遇到对齐问题,因为 int 应该在 4bytes 边界上对齐,而您的指针不是。

因此你想做很多很多问题:

  • 访问不存在的内存
  • 错误的内存访问(对齐)。

这行不通。

当您将 char 分配给 int 时,您创建了一个新变量,一个可以接收数据的 4 个字节的新位置。在这里,您无需创建可以保存该数据的新变量。

【讨论】:

    【解决方案3】:

    你说过:

    C++ 在表达式中将 char 隐式类型转换为 int(比 char 更大的数据类型),这意味着以下运行不会出现编译时错误:

    char a = 'a';
    int b = a;
    cout << b << endl;
    

    输出:

    97
    

    然后你问:

    为什么下面会抛出编译时错误:

    char a = 'a';
    char* str = &a;
    int* ptr;
    ptr = str;
    

    在您的第一个示例中,您声明了一个名为 achar 变量,并为其分配了字符 'a'。然后声明一个名为bint 变量并将其赋值为a。然后你打电话给coutb。这给出了预期的值97

    这里发生的是编译器会将 char a 的值隐式转换为整数。您看到值97 的原因是因为这是为小写a 分配的ASCII 代码。这里的可变大小无关紧要。


    在您开始询问编译器错误的第二个示例中,如下所示:

    您声明与上面相同的char 变量,并为其分配相同的字符值a。 这一次您创建一个pointer 到一个char 并将其命名为str 并将其分配给a 的地址。 str 现在指向 a。接下来,您为名为@9​​87654347@ 的int 创建了一个pointer,然后您尝试将str 分配给ptr。是的,所有指针在内存中的大小都相同,但是您在这里无法理解的是指针寻址的工作原理。由于您没有分别使用newdelete,因此这些指针位于堆栈上。所以在我的机器上我运行了这段代码:

    #include <iostream>
    
    int main() {
        char a = 'a';
        char* str = &a;
        std::cout << &str << '\n'; // print str's address
        int* ptr; // don't assign ptr to anything...
        std::cout << &ptr << '\n'; // print ptr's address
    }
    

    在我的机器上输出是:

    003BFC34  // this is the stack address of str
    003BFC28  // this is the stack address of ptr
    

    是的,两个指针本身通常在 32 位机器上占用 4 个字节的内存。但是,str 指向 1 字节的 char 类型,ptr 指向 32 位机器上的 4 字节 int 类型。

    因此,当您尝试将一个指针分配给另一个时;这仅在指针类型为相同类型时才有效!否则,您将遇到编译器错误或UB

    您在第一种情况下的假设是char 变成了int,但事实并非如此。在第一种情况下发生的情况是,它采用1 byte 表示的值,并将其隐式转换为采用4 bytes 的整数类型,而小写a 的整数表示是ASCII 的值@ 987654363@.


    因此您的第二种情况将无法编译:

    int main() {
        char a = 'a';
        char* str = &a;
        int* ptr = str; // fails to compile.
        return 0;
    }
    

    但是,有一种方法可以将指针从一种类型转换为另一种类型

    int main() {
        char a = 'a';
        char* str = &a;
        int* ptr = (int*)(str); // C Style Cast - Will Compile!
        int* ptr = reinterpret_cast<int*>( str ); // This will compile!
        return 0;
    }
    

    【讨论】:

    • 如果之前有另一个char,或者是一个short,那么如果你访问ptr,这将在执行过程中崩溃。
    【解决方案4】:

    当您将 int 值分配给 char 变量(反之亦然)时,编译器会隐式执行转换。 但是如果将 int 类型的指针分配给 char 变量的地址,这是非法的,因为它是 int 指针,它应该指向 int 变量。 另一个方向是一样的,char 指针应该指向 char 整数。 原因是因为在内存中 char 用一个字节表示,而 int 用四个字节表示。 这对于内存分配和释放很重要。

    【讨论】:

      猜你喜欢
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多