有关存储过程和功能共享的问题

问题描述

1)为什么我们不能在c中使用虚拟地址来代替变量,例如为什么要写int x呢?我们可以创建一个指向栈中第一个地址的指针,例如int * x = 1; ,如果我们喜欢声明第二个变量。 我们使用了下一个地址,例如int * y = 2。 或者我们可以使用堆栈中最后一个地址作为动态数组,而不是使用堆。

2) 函数是否共享相同的堆栈,如果它们共享,为什么我们不能在函数之外访问函数的局部变量。 我认为他们没有,但是我看不到函数上下文的变化,因为他们没有同时朗诵

3) 长类型是否在堆栈中占用两个地址,每个地址均为4个字节?

如果不是,则更改数学运算符

解决方法

  1. 为什么我们不能在c中使用虚拟地址来代替变量,例如为什么要写int x呢?我们可以创建一个指向栈中第一个地址的指针,例如int * x = 1; ,如果我们喜欢声明第二个变量。我们使用了下一个地址,例如int * y = 2。或者我们可以使用堆栈中最后一个地址作为动态数组,而不是使用堆。

好吧,您可以使用虚拟地址来代替变量,例如int* a=(int*)0x8000B,它仅在没有OS的环境中才能工作,例如在Bootloader中,因为如果使用了地址,则加载的程序通常是不同的操作系统。

您可以执行int* x=(int*)1int* x=(int*)5,但是在某些体系结构上可能会崩溃,因为这些体系结构与sizeof(int)的倍数不对齐(通常为2或4个字节)。 此外,如果您在没有操作系统的情况下编写程序,则该地址仅适用于此类地址,因为大多数操作系统会保留前几页。 ==>您无法对他们做任何事情。

我们可以使用堆栈中最后一个地址作为动态数组,而不是使用堆。

对不起,我真的不明白你的意思。堆栈不是动态数组,它只是一个内存地址和一些可用空间(例如“普通” PC上为2MB或嵌入式设备中只有几百个字节)。

  1. 函数共享相同的堆栈,如果它们共享,为什么我们不能在函数之外访问函数的局部变量。我认为他们没有,但是我看不到函数上下文的变化,因为他们没有同时朗诵

是的,它们共享相同的堆栈。 您可以通过一些技巧来访问它们,但是这些都是非常邪恶的。 假设您有一个函数_start。它从一个空堆栈开始(rbp = 0x1000,rsp = 0x1000)。然后,一些局部变量分配在堆栈上。 (rbp = 0x1000,rsp = 0xff0)。之后,它将调用main。 要跳转到的地址存储在堆栈中,并且更新了基本指针。 现在,堆栈指针和堆栈基指针具有以下地址:rbp = 0xfe8,rsp = 0xfe8 由于SysV-ABI要求16字节对齐,因此您必须再次减去8字节。 rbp = 0xfe8,rsp = 0xfe0。 现在,您可以从使用movq 22(%rsp),%rax开始访问一些局部变量。您现在可能拥有本地的一部分或整个本地。 每次对源代码或编译器标志进行细微更改,此技巧都会失败。

  1. long类型是否在堆栈中占用两个地址,每个地址均为4个字节?

否,长型占用栈中sizeof(long)个字节。地址的大小固定。四个(32位系统)或八个(64位系统)。

,

例如写int x;我们可以创建一个指向堆栈中第一个地址的指针

因为C比汇编程序更高级。 C语言不知道也不关心堆栈的存在。与汇编程序相比,高级语言的主要好处之一是消除了手动堆栈管理。因为汇编器中最常见的错误之一就是忘记在堆栈上压入/弹出某些内容-您永远不会遇到C语言中的错误,因为处理堆栈的指令是由编译器生成的。

因此C程序员不希望手动处理堆栈,主要是因为这样做很麻烦。您描述的伪代码与汇编程序的工作方式非常接近,汇编程序通常与堆栈指针有关。 “读取内存位置SP + 3”等。

或者我们可以使用栈中最后一个地址作为动态数组,而不是使用堆

否,因为堆栈的大小有限,并且作为ABI调用约定的一部分,还用于存储寄存器和返回地址。堆是一个较高层的概念,可以存储大块数据并与同一进程内的所有内容共享,甚至与其他进程共享,具体取决于系统。

编程老师将事情简化很多并说有两种形式的内存是一个常见的问题:堆栈和堆。然后,学生迷上了这两个,并开始做出各种疯狂的结论。实际上,主流计算机具有.stack.data.bss.heap.rodata.text和其他各种细分市场(通常是提到的)。变量可以存储在任何这些段中。例如,如果它们被优化为寄存器访问而不是存储在堆栈中,则它们最终会与.text内部的程序代码混合在一起。

函数共享相同的堆栈

如果您的意思是如果不同函数中的局部变量共享同一堆栈,那么是的,它们在正常情况下(假设单线程,单进程)也会这样做。

long类型是否在堆栈中占用两个地址,每个地址均为4个字节?

标准未指定long的大小,该大小可能为4或8个字节。分配它们的位置取决于上下文。

,
  1. 为什么我们不能在c中使用虚拟地址来代替变量,例如为什么要写int x呢?我们可以创建一个指向栈中第一个地址的指针,例如int * x = 1; ,如果我们喜欢声明第二个变量。我们使用了下一个地址,例如int * y = 2。或者我们可以使用堆栈中最后一个地址作为动态数组,而不是使用堆。

在C中,如果要堆栈存储,则可以声明局部变量或使用alloca分配堆栈内存。例如,我们可以这样做:

#include <iostream>

int main()
{
    typedef struct {
        int x;
        int y;
    } myStruct;

    myStruct *p = (myStruct *) alloca ( sizeof myStruct );

    p -> x = 100;
    p -> y = 200;
    p -> x += 100;
}

这为我们提供了xy的存储空间,可以通过p->xp->y进行引用。

但是,使用局部变量要简单得多,并且要求编译器做更少的工作来确定局部变量甚至不需要堆栈存储,它们可以直接存在于CPU寄存器中。

  1. 函数共享相同的堆栈,如果它们共享,为什么我们不能在函数之外访问函数的局部变量。我认为他们没有,但是我看不到函数上下文的变化,因为他们没有同时朗诵

对于每个线程,都有一个动态调用链,该线程中的所有函数都为局部变量共享同一堆栈。更具体地说,函数调用从概念上激活了堆栈中的帧或记录。

确实存在允许非本地引用的语言,即非本地引用但不是全局引用。这样的语言通常支持嵌套在函数内的函数。特别是对于一流的函数(函数指针),这些通常称为闭包。在像Pascal这样的较老的语言中,使用非局部变量可以为穷人提供面向对象的编程能力。要支持其中的任何一种,都需要在幕后,框架指针和反向链接等方面投入大量精力.C编程语言选择不实现嵌套函数,我认为这是出于简化目的。可以使用更通用的堆对象(但需要手动分配和释放)来代替它。

  1. long类型是否在堆栈中占用两个地址,每个地址均为4个字节?

可能是的。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...