是否可以在内存中为变量分配您想要的地址?
我试图这样做,但我收到错误消息“左值需要作为赋值的左操作数”。
int main() {
int i = 10;
&i = 7200;
printf("i=%d address=%u", i, &i);
}
Run Code Online (Sandbox Code Playgroud)
我的方法有什么问题?在 C 中有什么方法可以将我们想要的地址分配给变量吗?
void f()
{}
void test()
{
auto fn_1 = f;
auto fn_2 = &f;
assert(fn_1 == fn_2); // OK
fn_1(); // OK
fn_2(); // OK
(*fn_1)(); // OK
(*fn_2)(); // OK
(**fn_1)(); // OK
(**fn_2)(); // OK
(***fn_1)(); // OK
(***fn_2)(); // OK
}
Run Code Online (Sandbox Code Playgroud)
这些行为是否由 C++ 标准明确定义?
请注意:我知道这些差异,所以这个问题不是要知道它们之间的区别,而是为了别的东西。
我把我的理解和知识(对于那些不知道的人)放在下面,这些知识来自可靠的信息来源。
Gigabyte 和 Gigabit 是十进制表示法,分别代表字节和位的 10 次方。
Gibibyte 和 Gibibit 用于二进制表示法,分别表示字节和位的 2 次幂。
为了符号,字节将始终表示为 B,位将始终表示为 b。
据我所知,以上信息属实。
下面是引用,可以在很多地方看到,包括Wiki 32-bit,Stackoverflow 32 bit等。 如下所示,32 位内存地址可以访问 4 GiB(这意味着 4 gibibyte 而不是 4 gibibit)字节可寻址内存。
因此,具有 32 位内存地址的处理器可以直接访问 4 GiB 的字节可寻址内存。
问题:
我真的很困惑(实际上快疯了)2^32位内存地址如何访问 4 gibi字节的可寻址内存?不应该是 4 Gibibit 或 0.5 …
我正在阅读Intel x86_64 指南 vol.1以刷新内存寻址的工作方式。
仍然,
3.7.5 指定偏移
内存地址的偏移部分可以直接指定为静态值(称为位移)或通过由以下一个或多个组件组成的地址计算指定:
• 位移— 8 位、16 位或32 位值。
我在Agner Fog 的汇编指南中读到,当与 (r/e)ax 寄存器一起使用时,64 位绝对寻址是可能的。
所以..
是否可以使用具有 64 位地址的绝对寻址来 jmp、mov 和 call(使用所有寄存器),或者我是否必须继续使用 Base + 位移组合?
我有以下几点class:
TTest = class
private
FId: Integer;
FSecField: Integer;
FThirdField: Integer;
public
constructor Create(AId, ASecField, AThirdField: Integer);
// .....
end;
Run Code Online (Sandbox Code Playgroud)
然后我创建一个TObjectDictionary这样的:
procedure TMainForm.btnTestClick(Sender: TObject);
var
TestDict: TObjectDictionary<TTest, string>;
Instance: TTest;
begin
TestDict := TObjectDictionary<TTest, string>.Create([doOwnsKeys]);
try
TestDict.Add(TTest.Create(1, 1, 1), '');
if TestDict.ContainsKey(TTest.Create(1, 1, 1)) then
ShowMessage('Match found')
else
ShowMessage('Match not found');
Instance := TTest.Create(1, 1, 1);
TestDict.Add(Instance, 'str');
if TestDict.ContainsKey(Instance) then
ShowMessage('Match found')
else
ShowMessage('Match not found');
finally
TestDict.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
结果是:“找不到匹配项”、“找到匹配项”。我应该怎么做才能比较每个键的字段值而不是它们的地址?
我开始学习 C++,现在我想知道我是否也可以在 Swift 中做一些事情。
我从来没有真正想过当我们将变量作为参数传递给 Swift 中的函数时会发生什么。
让我们使用类型变量string作为示例。
在 C++ 中,我可以通过制作函数的副本或传递引用/指针来将参数传递给函数。
void foo(string s)或者void foo (string& s); 在第一种情况下,将创建原始变量的副本,并且foo将收到一个副本。在第二种情况下,我基本上传递内存中变量的地址而不创建副本。
现在在 Swift 中我知道我可以将函数的参数声明为inout,这意味着我可以修改原始对象。
1) func foo(s:String)... 2) func testPassingByReference(s: inout String)...
我对 String 进行了扩展以打印对象的地址:
extension String {
func address() -> String {
return String(format: "%p", self);
}
}
Run Code Online (Sandbox Code Playgroud)
结果并不是我所期望看到的。
var str = "Hello world"
print(str.address())
Run Code Online (Sandbox Code Playgroud)
0x7fd6c9e04ef0
func testPassingByValue(s: String) {
print("he address of s is: \(s.address())")
}
func testPassingByReference(s: inout String) …Run Code Online (Sandbox Code Playgroud) 我试图计算最大内存大小,知道地址的位长和内存单元的大小。
我的理解是,如果地址是 n 位,则有 2^n 个内存位置。但是要计算机器的实际内存大小,您需要将地址数乘以内存单元的大小。那是对的吗?
换一种方式,
步骤 1:以位(n 位)为单位计算地址的长度 步骤 2:计算内存位置的数量 2^n(位) 步骤 3:取内存位置的数量并将其乘以内存单元的字节大小.
例如,如果每个单元格是 2 个字节,我是否会将 2^n 位(地址长度)乘以每个存储单元的 2 个字节。
那么总内存将是 2^n 位(地址大小)* x 字节(单元格大小)?
有些架构具有多个地址空间,著名的例子是真正的哈佛架构,但 OpenCL 也具有此属性。
C 编译器可能为此提供一些解决方案,其中之一是命名地址空间,支持特殊的指针限定符来指示指针的地址空间,但也可能存在其他解决方案。
我不知道它们,并且在我使用的架构(8 位 AVR)上,还有另一种解决方案来处理该问题,即专门的宏 ( )pgmspace.h来处理 ROM 中的数据。但是对这些没有类型检查,并且它们(在我看来)使代码变得丑陋,所以在我看来,使用命名地址空间是一种更好的,甚至可能更便携的方式来处理问题(可移植的通过为地址空间限定符提供空定义,可以轻松地将这样的软件移植到具有单个地址空间的目标。
然而,在我从其可用性中了解到的上一个问题中,建议使用命名地址空间的解决方案被严重否决,此处:如何使两个其他相同的指针类型不兼容
反对者没有提供任何解释,我自己也没有找到任何解释,对我来说,命名地址空间似乎是处理问题的一种很好且功能完善的方式。
有人能提供解释吗?为什么不应该使用命名地址空间?(倾向于具有多个不同地址空间的目标上可用的任何其他方法)
上下文:我正在为我的程序使用线程清理程序,它显示我的程序存在数据争用。我 100% 确定为什么(也许有太多内存访问),线程清理程序不会给出无效访问的确切堆栈跟踪。只有
Previous read of size 4 at 0x7b1800004140 by thread T36:
[failed to restore the stack]
Run Code Online (Sandbox Code Playgroud)
我尝试history_size=7根据文档设置运行线程清理程序时,但仍然无法获取堆栈跟踪。
我知道C/C++出于安全考虑支持地址随机化,所以我用它-fno-stack-protector来编译我的程序,这使得多次运行时无效地址访问相同。
我想知道如何获取该地址上驻留的变量,以便我可以直接获取我非法访问它的位置?
我使用 bazel 作为我的构建系统,它间接依赖于 clang v13.0.0。