- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在通过 K&R C 工作,这句话对我来说很突出:
A pointer is a variable that contains the address of a variable.
我总是假设(也许是错误的)底层的变量必须包含名称、类型和内存中某个位置的地址。即:虽然变量可以被视为值,但编译器必须知道这些值存储在内存中的位置,因此变量也必须是指针(概念上,而不是形式上)。
但现在我不太确定了。文本似乎暗示变量在某种程度上比指针更基本。
变量到底是什么?它们是否像引擎盖下的指针,或者它们在某些方面有所不同?特别希望在内存分配方式的背景下理解这一点。
编辑:对于那些参与语义辩论的人...我感兴趣的是理解_平均_用例,而不是标准指定或未指定的内容,尽管我应该指定。出于功能目的,假设在 unix 机器上使用 gcc 或类似工具编译 C。谢谢!
最佳答案
“变量”的具体构成因语言而异。使用什么样的运行时环境也很重要 - native 二进制文件 (C/C++/Fortran/Cobol/Pascal)、虚拟机中的字节码 (Java/C#/Scala/F#)、源代码级解释器 (old-skool) BASIC、bash/csh/sh) 等
就 C 而言,变量只是一 block 足够大以保存指定类型值的内存块 - 没有与该内存块关联的元数据来告诉您有关其名称的任何信息(通常不是保存在机器代码中),它的类型,是否是数组的一部分,等等。IOW,如果您在正在运行的程序中检查内存中的整数变量,您所看到的只是存储在该整数中的值。您不会看到存储有关该变量的任何其他信息。
在翻译期间(即,在编译代码时),编译器维护一个内部表,用于跟踪变量、变量名称、类型、范围、可见性等。但是,没有一个该信息(通常)会放入生成的机器代码中。 auto
(本地)变量通常通过给定堆栈地址的偏移量来引用。 静态
变量通常具有固定地址。不同类型的值使用不同的机器代码指令来处理(例如,通常有单独的指令来处理整数和 float )。
指针变量只存储一个地址。该地址的确切格式会因系统而异,但在现代 x86 和类似系统上,它本质上是一个无符号整数值。在分段内存系统上,它可能是一对值(页号和偏移量)。
编辑
C 代码通常被编译为 native 二进制文件(尽管至少有一个针对 Java VM 的编译器,并且可能存在针对其他虚拟机的编译器)。在类似 x86 的系统上,正在运行的 native 二进制文件通常在(虚拟!)内存中布局如下: +-------------------------+
High address: | Environmental variables |
| and command line args |
+-------------------------+
| Stack |
| | |
| V |
| ^ |
| | |
| Heap |
+-------------------------+
| Read-only data items |
+-------------------------+
| Global data items |
+-------------------------+
| Program text (machine |
Low address: | code) |
+-------------------------+
确切的细节因系统而异,但这是一个不错的整体 View 。
每次调用函数(包括 main
)时,都会从堆栈中获取内存以构建所谓的堆栈帧。堆栈帧包含函数参数(如果有)、局部变量(如果有)、前一个堆栈帧的地址以及函数返回后要执行的下一条指令的地址的空间。
+--------------------+
High address: | Function arguments |
+--------------------+
| Return address |
+--------------------+
| Prev frame address | <-- %rbp/%ebp (frame pointer)
+--------------------+
Low address: | Local variables | <-- %rsp/%esp (stack pointer)
+--------------------+
%rsp
(64 位)或 %esp
(32 位)寄存器存储堆栈顶部的地址(在 x86 上,堆栈增长“向下”向递减地址),%rbp
(64 位)或 %ebp
(32 位)寄存器存储堆栈帧的地址。函数参数和局部变量通过帧指针的偏移量来引用,例如
-4(%rpb) -- object starting 4 bytes "below" current frame address
32(%rbp) -- object starting 32 bytes "above" current frame address
这是一个示例 - 我们有一个函数 foo
,它接受两个 int
参数并具有两个 int
局部变量:
#include <stdio.h>
void foo( int x, int y )
{
int a;
int b;
a = 2 * x + y;
b = x - y;
printf( "x = %d, y = %d, a = %d, b = %d\n", x, y, a, b );
}
这是为该函数生成的程序集(MacOS 10.13,LLVM 版本 9.1.0):
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _foo ## -- Begin function foo
.p2align 4, 0x90
_foo: ## @foo
.cfi_startproc
## BB#0:
pushl %ebp
Lcfi0:
.cfi_def_cfa_offset 8
Lcfi1:
.cfi_offset %ebp, -8
movl %esp, %ebp
Lcfi2:
.cfi_def_cfa_register %ebp
pushl %ebx
pushl %edi
pushl %esi
subl $60, %esp
Lcfi3:
.cfi_offset %esi, -20
Lcfi4:
.cfi_offset %edi, -16
Lcfi5:
.cfi_offset %ebx, -12
calll L0$pb
L0$pb:
popl %eax
movl 12(%ebp), %ecx
movl 8(%ebp), %edx
leal L_.str-L0$pb(%eax), %eax
movl 8(%ebp), %esi
shll $1, %esi
addl 12(%ebp), %esi
movl %esi, -16(%ebp)
movl 8(%ebp), %esi
subl 12(%ebp), %esi
movl %esi, -20(%ebp)
movl 8(%ebp), %esi
movl 12(%ebp), %edi
movl -16(%ebp), %ebx
movl %eax, -24(%ebp) ## 4-byte Spill
movl -20(%ebp), %eax
movl %eax, -28(%ebp) ## 4-byte Spill
movl -24(%ebp), %eax ## 4-byte Reload
movl %eax, (%esp)
movl %esi, 4(%esp)
movl %edi, 8(%esp)
movl %ebx, 12(%esp)
movl -28(%ebp), %esi ## 4-byte Reload
movl %esi, 16(%esp)
movl %edx, -32(%ebp) ## 4-byte Spill
movl %ecx, -36(%ebp) ## 4-byte Spill
calll _printf
movl %eax, -40(%ebp) ## 4-byte Spill
addl $60, %esp
popl %esi
popl %edi
popl %ebx
popl %ebp
retl
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "x = %d, y = %d, a = %d, b = %d\n"
.subsections_via_symbols
这是我们的堆栈框架的样子:
+---+
High address: | y |
+---+
| x |
+---+
| | return address
+---+
| | address of previous frame
+---+
| a |
+---+
| b |
+---+
现在,这就是 32 位世界中的情况。 64 位变得有点复杂 - 一些函数参数在寄存器中而不是在堆栈上传递,因此上面漂亮整洁的图片崩溃了。
现在,我正在谈论运行时变量的概念,我认为这就是您所问的问题。
关于c - C 变量在底层包含哪些信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51658307/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!