Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 投射原语时的记忆解释_C++_C_Casting - Fatal编程技术网

C++ 投射原语时的记忆解释

C++ 投射原语时的记忆解释,c++,c,casting,C++,C,Casting,在C/C++等语言中,当我们这样做时: char c = 'A'; 我们分配内存以二进制形式存储数字65: 从左到右填充 如果我们这样做: int i = (int) c; 据我所知,我们是在对编译器说,它应该将布局的位模式解释为从左到右的stuff\u 01000001\uuu00000000\uu00000000\u00000000\u从右到右的stuff\u,这可能是65,也可能不是 当我们在手术中执行强制转换时,也会发生同样的情况 cout << (int) c <

在C/C++等语言中,当我们这样做时:

char c = 'A';
我们分配内存以二进制形式存储数字65:

从左到右填充

如果我们这样做:

int i = (int) c;
据我所知,我们是在对编译器说,它应该将布局的位模式解释为
从左到右的stuff\u 01000001\uuu00000000\uu00000000\u00000000\u从右到右的stuff\u
,这可能是65,也可能不是

当我们在手术中执行强制转换时,也会发生同样的情况

cout << (int) c << endl;

coutC中的强制转换不会重新解释任何内容。它们是价值转换
(int)c
意味着取
c
的值并将其转换为
int
,这基本上对所有系统都是无效的。(如果
char
的范围大于
int
的范围,例如如果
char
int
都是32位,但
char
是无符号的,则它可能无法成为no op。)

如果要重新解释值的基本表示(位模式),该值必须首先作为对象(左值)存在,而不仅仅是表达式的值(通常称为“右值”,尽管C标准中不使用这种语言)。然后,您可以执行以下操作:

*(new_type *)&object;
但是,除非
new\u type
是字符类型,否则这会通过违反别名规则来调用未定义的行为。C++有一种“重新解释的转换”来完成这一点,它可以避免打破混淆规则,但是由于我对C++不熟悉,所以我不能提供关于它的详细信息。
在C++实例中,得到不同结果的原因是运算符重载。代码>(int)'A'
不会更改值或其解释方式;相反,具有不同类型的表达式会导致不同的
操作符重载当您分配一个char时,左边或右边都没有stuff。它是八位的,仅此而已。因此,当您将8位值转换为32位时,仍然会得到65:

0100.0001
0000.0000.0000.0000.0000 0100.0001

没有魔法,就没有运气

我是幸运还是错过了一些基本的东西

是的,您缺少一些基本信息:编译器不会从内存中读取
char
,就像内存表示
int
一样。相反,它将
char
读取为char,然后符号扩展值以适合
int
,因此
char
-1
也变为
int
-1
。符号扩展意味着将
1
s或
0
s添加到被扩展的最高有效字节的左侧,具体取决于该数字的符号位。无符号类型始终用零*填充

符号扩展通常通过执行专用硬件指令在寄存器中完成,因此它运行得非常快。

*如注释中所述,
char
类型可能是有符号的,也可能是无符号的,这取决于C实现。

问题是,这种行为可能会因编译到的平台和使用的编译器而改变

ISO标准将(int)定义为强制转换。 在本例中,编译器将解释(int)c,就像c中的静态_cast(c)//一样++

现在,您很幸运,您的编译器将(int)解释为一个简单的强制转换。这是任何C/C++编译器的共同行为,但是可能有一些邪恶的,没有名字的C++编译器,它们会对那个编译器进行重新解释,结果会出现不可预测的结果(取决于平台)。 这就是为什么您应该使用100%舒尔的静态_cast(c) 如果你想重新解释它,当然要重新解释(c)

但是,同样,它通常是c样式的强制转换,因此c将被强制转换为整数。

在代码中,“i”有自己的地址,“c”有自己的地址。正在将值从c“复制”到i。 至于“(int)c”,同样的情况也会发生。尽管编译器为我们这样做,如下所示

     |--- i ---|- c-|  
 0x01 0x02 0x03 0x04
+--------------------......
| 00 | 00 | 08 | 08 |......  
+--------------------......
如果这是基于指针的分配,您应该是正确的

e、 g


这里*p将有来自mem地址0x02和0x03的组合值。

将char转换为int不是不可操作的。它需要对值进行零扩展或符号扩展,这取决于char是否有符号(并且忽略了C标准允许的深奥实现)。@Eric:在C语言的抽象机器中,这是一个不可选项。42是42。这是一个价值观。表示仅在存储在对象中时才起作用。即使在具有寄存器和零/符号扩展的物理机器中,如果需要,扩展操作也可能发生在与强制转换完全不同的点上。子句“基本上对所有系统都是不可操作的”涉及系统上的操作,而不是C抽象机中的操作。扩展操作可能发生在与强制转换完全不同的点的说法是毫无意义的,因为扩展在物理机器中,而强制转换在C源中。关键是从char到int的转换不一定是零成本的;有时它确实需要处理器的时间和精力来计算。换言之,我所说的“无运算”的意思是,没有一个C代码的行为(甚至其从编译器输出的机器代码)会通过将
C
更改为
(int)而改变c
除了c
的大小。字符不一定是8位,也不一定是65位。在大多数情况下,这两个事实都是正确的。ASCII和sizeof(char)=1是默认行为。当然,OP本身假设“A”=65…@R..:是的,C标准规定字符是一个字节。它没有指定一个字节是八位。@dda:ASCII不是“默认值”。字符集取决于C实现。有些C实现使用EBCDIC,有些可能使用专门的字符集。字符类型可以是有符号的,也可以是无符号的,这取决于C
 0x01 0x02 0x03
+---------------......
| 07 | 10 | 08 |......
+---------------......
int *p;
char c = 10;
p = &c;
print(*p); //not a real method just something that can print.