无法在赋值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 = <value>
之后执行所有操作,则一切正常,因为您只更改了一个字节,但*ptr = <value>
将写入多个字节,导致意外后果等
【讨论】:
这是我无法理解的。在数据类型的隐式类型转换中,即使那时 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;
在您的第一个示例中,您声明了一个名为 a
的 char
变量,并为其分配了字符 'a'
。然后声明一个名为b
的int
变量并将其赋值为a
。然后你打电话给cout
b
。这给出了预期的值97
。
这里发生的是编译器会将 char a
的值隐式转换为整数。您看到值97
的原因是因为这是为小写a
分配的ASCII
代码。这里的可变大小无关紧要。
在您开始询问编译器错误的第二个示例中,如下所示:
您声明与上面相同的char
变量,并为其分配相同的字符值a
。
这一次您创建一个pointer
到一个char
并将其命名为str
并将其分配给a
的地址。 str
现在指向 a
。接下来,您为名为@987654347@ 的int
创建了一个pointer
,然后您尝试将str
分配给ptr
。是的,所有指针在内存中的大小都相同,但是您在这里无法理解的是指针寻址的工作原理。由于您没有分别使用new
和delete
,因此这些指针位于堆栈上。所以在我的机器上我运行了这段代码:
#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 * [关闭]的主要内容,如果未能解决你的问题,请参考以下文章