C ++在表达式中将char隐式转换为int(比char更大的数据类型),这意味着以下运行不会出现编译时错误:
self.a = 1
为什么以下内容会引发编译时错误:
char a = 'a';
int b = a;
cout << b << endl;
// output
97
由于指针的大小固定(取决于32/64位操作系统),无论它们指向的是哪种数据类型,请帮助我理解为什么这种转换是非法的。
答案 0 :(得分:3)
“ 因为指针的大小是固定的”,问题不在于指针的大小,而是指向类型的 char 不是 int ,因此 char * 不是 int *
如果您在*str = <value>
之后执行所有操作就可以了,因为您只更改了一个字节,但是*ptr = <value>
会写入一个以上的字节,从而产生意外的后果等
答案 1 :(得分:1)
您想要做的是未定义的行为。
您从char
开始并获得指向它的指针。没关系。例如,指针可以是0x01
。然后您说,实际上是指向1个字节的指针,让我们使其指向一个4个字节的指针(对于int
为32位假设)。
显然,这行不通。其他3个字节从哪里来?
然后,假设它确实起作用。您会遇到对齐问题,因为int应该在4bytes的边界上对齐,而指针没有对齐。
因此要解决很多问题
这行不通。
当将char分配给int时,您将创建一个新变量,一个具有4个字节的新位置,可以接收您的数据。在这里,您不会创建可以保存该数据的新变量。
答案 2 :(得分:1)
您说过:
C ++在表达式中隐式将char转换为int(比char更大的数据类型),这意味着以下运行不会出现编译时错误:
char a = 'a'; int b = a; cout << b << endl;
输出:
97
然后您问:
为什么以下内容会引发编译时错误:
char a = 'a'; char* str = &a; int* ptr; ptr = str;
在第一个示例中,您声明一个名为char
的{{1}}变量,并为其分配字符a
。然后,声明一个名为'a'
的{{1}}变量,并为其分配值int
。然后,您在b
上呼叫a
。这样得出的值为cout
。
这里发生的是编译器会将char b
的值隐式转换为整数。您看到值97
的原因是,这是为小写字母a
分配的97
代码。这里的变量大小无关紧要。
在第二个示例中,您开始询问编译器错误如下:
您声明与上述相同的ASCII
变量,并为其分配相同的字符值a
。
这次,您将char
创建到a
,并将其命名为pointer
,并将其分配给char
的地址。 str
现在指向a
。接下来,您为名为str
的{{1}}创建了a
,然后尝试将pointer
分配给int
。是的,所有指针在内存中的大小都相同,但是您在这里无法理解的是指针寻址的工作方式。由于您没有分别使用ptr
和str
,所以这些指针位于堆栈中。因此,在我的机器上,我运行了以下代码:
ptr
在我的机器上,输出为:
new
是的,两个指针本身通常占用32位计算机上的4个字节的内存。但是,在32位计算机上,delete
指向1个字节的char类型,而#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
}
指向4个字节的int类型。
因此,当您尝试将一个指针分配给另一个指针时;这仅在指针类型为相同类型时才有效!否则,您将遇到编译器错误或003BFC34 // this is the stack address of str
003BFC28 // this is the stack address of ptr
。
您在第一种情况下的假设是str
成为ptr
,事实并非如此。第一种情况是,它采用UB
表示的值,并将其隐式转换为采用char
的整数类型,而小写字母int
的整数表示为1 byte
的{{1}}值。
因此,您的第二种情况将不会编译:
4 bytes
但是,有一种方法可以将指针从一种类型转换为另一种类型
a
答案 3 :(得分:0)
当您将int值分配给char变量时,反之亦然,编译器将隐式进行强制转换。 但是,如果将int类型的指针分配给char变量的地址,则是非法的,因为它是int指针,因此应指向int变量。 另一个方向是相同的,char指针应指向char整数。 原因是因为在内存中char以一个字节表示,而int用四个字节表示。 这对于内存分配和释放很重要。