无法在赋值c ++中将char *转换为int * [关闭]

Posted

技术标签:

【中文标题】无法在赋值c ++中将char *转换为int * [关闭]【英文标题】:cannot convert char* to int* in assignment c++ [closed] 【发布时间】: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 字节时会发生什么情况? 【参考方案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 用四个字节表示。 这对于内存分配和释放很重要。

【讨论】:

以上是关于无法在赋值c ++中将char *转换为int * [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在c中将字符串转换为int [重复]

在 C 和 C++ 中将 char 转换为 int

在 C 和 C++ 中将 int 值转换为 char 指针差异

如何在C中将char转换为整数? [复制]

在C中将char从大端转换为小端

在 C 中将字符串数组转换为 Int 数组的最佳方法