C 声明字符串时保留了多少内存?

C 声明字符串时保留了多少内存?,c,memory-management,C,Memory Management,在内存方面,当我声明如下内容时,会发生什么情况: char-arr[4] 为arr保留了多少字节 当我在arr中“strcpy”一个长度为4的字符串时,如何容纳空字符串 我正在编写一个套接字程序,当我试图在arr[4](即第5个内存位置)添加NULL后缀时,我最终替换了程序中其他一些变量的值(溢出),陷入了一片混乱 任何关于编译器(我使用的是gcc)如何管理内存的描述?sizeof(arr)字节都会被保存*(加上编译器希望在其周围添加的任何填充,尽管这并不适用于数组本身)。在具有堆栈的实现上,这

在内存方面,当我声明如下内容时,会发生什么情况: char-arr[4]

为arr保留了多少字节

当我在arr中“strcpy”一个长度为4的字符串时,如何容纳空字符串

我正在编写一个套接字程序,当我试图在arr[4](即第5个内存位置)添加NULL后缀时,我最终替换了程序中其他一些变量的值(溢出),陷入了一片混乱

任何关于编译器(我使用的是gcc)如何管理内存的描述?

sizeof(arr)
字节都会被保存*(加上编译器希望在其周围添加的任何填充,尽管这并不适用于数组本身)。在具有堆栈的实现上,这只意味着向下移动堆栈指针
sizeof(arr)
字节。(这就是存储的来源。这也是自动分配速度快的原因。)

“\0”
不适用。如果将“abcd”复制到其中,则会出现缓冲区溢出,因为这总共占用5个字节,但只有4个字节。你进入未定义的行为地带,任何事情都可能发生

实际上,您迟早会损坏堆栈并崩溃,或者体验您所做的操作并覆盖附近的变量(因为它们也像数组一样被分配)。但是没有人能够确定会发生什么,因为它是未定义的

*这是
sizeof(char)*4
sizeof(char)
始终是1,所以是4个字节。

在C中,您要求的通常是您得到的
char arr[4]
正好是4个字节

但是引号中的任何内容都在末尾添加了一个“隐藏”空值,因此
char arr[]=“oops”保留5个字节

因此,如果您这样做:

char arr[4];
strcpy(arr, "oops");

…当您仅为4保留空间时,将复制5个字节(
o p s\0
)。接下来发生的任何事情都是不可预测的,而且往往是灾难性的。

当您定义一个类似于
char arr[4]
的变量时,它正好为该变量保留了4个字节。正如你所发现的,超出这一点的写作会导致标准所称的“未定义的行为”——一种委婉语,意思是“你搞砸了——不要那样做。”

这样的内存管理非常简单:如果它是一个全局内存,那么它将被分配到一个全局内存空间中。如果它是本地的,则通过从堆栈指针中减去适当的量来在堆栈上分配它。返回时,堆栈指针将被还原,因此它们不再存在(当调用另一个函数时,通常会被该函数的参数和局部变量覆盖)

到底发生了什么,在 内存,当我声明如下内容时: char-arr[4]

4*sizeof(char)
为字符串保留的堆栈内存字节数

当我 “strcpy”arr中长度为4的字符串

你不能。您只能有3个字符,第4个字符(即arr[3])应为'\0'字符,表示正确的字符串

当我试图在arr[4]处添加NULL后缀时


当您访问无效的内存位置时,该行为将未定义。在最好的情况下,您的程序将立即崩溃,但它可能会损坏堆栈并在以后某个时间点崩溃。

当您做出类似于
char arr[4]的声明时,编译器根据您的要求分配尽可能多的字节,即四个字节。编译器可能会分配额外的内存以适应高效的内存访问,但通常情况下,您会得到您所要求的

如果随后在同一个函数中声明另一个变量,则该变量通常会跟随内存中的
arr
,除非编译器再次进行某些优化。因此,如果您尝试写入
arr
,但写入的字符比实际分配给
arr
的字符多,则可以覆盖堆栈上的其他变量


这实际上不是gcc的功能。所有C编译器的工作方式基本相同。

+1明确指出sizeof(char)始终等于1。大小应为4chars+\0=>arr[5]注意,虽然
char arr[]=“oops”
为后面的NUL保留额外的字节,可以使用
char arr[4]=“oops”来抑制这一点取而代之。但是当然,如果没有NUL…=)次要nit,它就不能作为C字符串工作:你应该使用
NUL
'\0'
来引用终止符,而不是
NULL
(空指针常量)。@Arkku:我不知道编译器会用它做什么(我怀疑行为是未定义的)@jamesdlin:修复。
char-arr[4]=“oops”在标准C中定义;它等价于char-arr[4]={o',o',p',s}。看见