C/ c++指针技巧修复
C/C++ pointer trick fix
我正在尝试这个指针技巧,我不知道如何修复它,我在ubuntu 12.04 64位上运行g++ 4.6。查看下面的代码:
int arr[5];
arr[3] = 50;
((short*) arr)[6] = 2;
cout << arr[3] << endl;
逻辑是:因为short
是2个字节,int
是4个字节,我想改变arr[3]
的前2个字节,同时保持第二个2个字节的值为50。我只是把位模式弄乱了。不幸的是,sizeof(int*)
和sizeof(short*)
都是8字节。是否有一个类型转换,返回大小为2字节的指针?
更新:
我意识到这个问题写得很糟糕,所以我会修改它:我得到的cout << arr[3] << endl;
的输出是2。我想要得到的输出既不是2也不是50,而是一个很大的数字,表明int位模式的左边部分已经改变,而存储在arr[3]中的int的右边部分(第二个2位)仍然不变。
sizeof(int*)
和sizeof(short*)
都将是相同的——sizeof(void*)
也是一样——你要求的是指针的大小,而不是指针所指向的对象的大小。
使用sizeof(int)
或sizeof(short)
代替。
现在,对于您的代码片段,您正在对正在运行的机器的端序进行假设。在给定的平台上,int
的"第一部分"可以是具有较高地址的字节,也可以是具有较低地址的字节。
例如,你的内存块可能是这样布局的。假设最低位字节的索引是0,最高位字节的索引是1。在大端序架构中,int可能看起来像这样:
<------------- 4 bytes --------------->
+---------+---------+---------+---------+
| int:3 | int:2 | int:1 | int:0 |
| short:1 | short:0 | short:1 | short:0 |
+---------+---------+---------+---------+
注意int型的第一个short(在你的例子中应该是((short*) arr)[6]
)包含int型的最高有效位,而不是最低有效位。因此,如果覆盖((short*) arr)[6]
,则覆盖arr[3]
的最高有效位,这似乎是您想要的。但是x64不是一个大的端序机器。
在一个小的端序架构中,你会看到这样:
<------------- 4 bytes --------------->
+---------+---------+---------+---------+
| int:0 | int:1 | int:2 | int:3 |
| short:0 | short:1 | short:0 | short:1 |
+---------+---------+---------+---------+
会导致相反的行为——((short*) arr)[6]
将是arr[3]
的最低有效位,而((short*) arr)[7]
将是最高有效位。
我的机器恰好是这样做的——你的机器可能不同:
C:UsersBillyDesktop>type example.cpp
#include <iostream>
int main()
{
std::cout << "Size of int is " << sizeof(int) << " and size of short is "
<< sizeof(short) << std::endl;
int arr[5];
arr[3] = 50;
((short*) arr)[6] = 2;
std::cout << arr[3] << std::endl;
((short*) arr)[7] = 2;
std::cout << arr[3] << std::endl;
}
C:UsersBillyDesktop>cl /W4 /EHsc /nologo example.cpp && example.exe
example.cpp
Size of int is 4 and size of short is 2
2
131074
您的问题是由于端序。Intel的CPU是小端序的,这意味着int类型的第一个字节存储在第一个地址中。让我来举个例子:
假设arr[3]位于地址10:
然后arr[3] = 50;
将以下内容写入内存
10: 0x32
11: 0x00
12: 0x00
13: 0x00
, ((short*) arr)[6] = 2;
将以下内容写入内存
10: 0x02
11: 0x00
当你索引一个指针时,它会将索引乘以指向类型的大小。所以,你不需要一个2字节的指针
你做了很多可能站不住脚的假设。还有,指针的大小和问题有什么关系?
为什么不直接使用位掩码:
arr[3] |= (top_2_bytes << 16);
这应该设置上部16个字节而不干扰下部16个字节。
说了以上这些,标准禁止这样做:通过指向另一类型的指针设置变量是调用未定义行为。如果你知道你的机器是如何工作的(int
和short
的大小,字节序,…)和你知道你的编译器(很可能)是如何翻译你的代码的,那么你可能会逃脱它。当机器/编译器/月相发生变化时,会发生壮观的爆炸。
如果它赢得了任何性能,它将是最小的,甚至可能是净损失(很久以前我玩弄的一个编译器,玩"我可以比编译器更好地实现这个循环,我确切地知道这里发生了什么",为我的`label: ... if() goto label;
生成的代码比完全相同的本机编写的循环更糟糕:我的"智能"代码混淆了编译器,它的"循环模式"不适用)。
你不希望你的实际指针的大小是两个字节;这意味着它只能访问~16k的内存地址。然而,使用对short *的强制类型转换,将允许您每两个字节访问一次内存(因为编译器将该数组视为short数组,而不是int数组)。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错