Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我可以使用以0大小启动的数组:Char ch[0];_C++_Arrays_Char - Fatal编程技术网

C++ 为什么我可以使用以0大小启动的数组:Char ch[0];

C++ 为什么我可以使用以0大小启动的数组:Char ch[0];,c++,arrays,char,C++,Arrays,Char,这是我的代码: #include<iostream> using namespace std; int main(){ char ch[0]; cin >> ch; cout << ch; return 0; } 产出1: abcdefghijklmnopqrstuvwxyza (工作很好,但我不知道为什么) 输入2: abcdefghijklmnopqrstuvwxyzab 输出2: abcdefghijklmnopqr

这是我的代码:

#include<iostream>
using namespace std;
int main(){
    char ch[0];
    cin >> ch;
    cout << ch;
    return 0;
}
产出1:

abcdefghijklmnopqrstuvwxyza
(工作很好,但我不知道为什么)

输入2:

abcdefghijklmnopqrstuvwxyzab
输出2:

abcdefghijklmnopqrstuvwxyzab_
(请求输入)

输入3:

abcdefghijklmnopqrstuvwxyzabc
输出3: (运行时错误)

当output2请求输入时,我们将input2, 输出与输出2相同(再次请求输入), 当我们把input1或input2放进去时,output1或output2也会出现


有人能解释这种现象吗?为什么会发生这种情况?

大小为0的数组无效:

如果存在常数表达式(5.19),则其应为积分常数表达式,且其值应大于零

如果编译器接受它,那么它只是一个非标准扩展。GCC接受它,但如果您添加
-pedantic
选项,则会发出诊断:

warning: ISO C++ forbids zero-size array ‘arr’ [-pedantic]

尽管如此,读入非标准的零大小数组无疑会给您带来未定义的行为。

大小为0的数组无效:

如果存在常数表达式(5.19),则其应为积分常数表达式,且其值应大于零

如果编译器接受它,那么它只是一个非标准扩展。GCC接受它,但如果您添加
-pedantic
选项,则会发出诊断:

warning: ISO C++ forbids zero-size array ‘arr’ [-pedantic]

尽管如此,读入非标准的零大小数组无疑会给您带来未定义的行为。

您需要一个可以存储输入值的数组,这绝对无法处理

char ch[0];
这肯定是一个
分段
错误

$./a.out 
12345678901234567890
Segmentation fault (core dumped)

您需要将
ch
定义为输入所需的大小。

您需要一个可以存储输入值的数组,这绝对无法处理

char ch[0];
这肯定是一个
分段
错误

$./a.out 
12345678901234567890
Segmentation fault (core dumped)

您需要将
ch
定义为输入所需的大小。

基本上
char ch[0]
;是内存中定义的地址。 您将其传递给Cin,它开始从输入到它的字符处写入。 然后你传递同一个地址,它会试图理解它。 基本上打印每个字符,直到它运行到0


你必须做一些深入的调查,看看你为什么会看到这种行为,但这完全是浪费时间。行为是未定义的,不能保证它在任何方面都是可重复的。

基本上
charch[0]
;是内存中定义的地址。 您将其传递给Cin,它开始从输入到它的字符处写入。 然后你传递同一个地址,它会试图理解它。 基本上打印每个字符,直到它运行到0


你必须做一些深入的调查,看看你为什么会看到这种行为,但这完全是浪费时间。行为是未定义的,不能保证它在任何方面都是可重复的。

正如stfrabbit指出的,标准明确禁止声明大小为零的数组。但是,
gcc
允许将这类事情作为扩展,我们不会对此进行讨论


发生了什么事?嗯,当需要寻找
操作符>
操作符的可接受重载时,正如stfrabbit指出的,标准明确禁止声明大小为零的数组。但是,
gcc
允许将这类事情作为扩展,我们不会对此进行讨论


发生了什么事?好的,当需要寻找
操作符>>
操作符的可接受重载时,大多数编译器只会将数组设置为具有真实的开始地址,但不会占用任何空间,因此堆栈或结构中的后续变量将从它们在0大小的数组根本不存在时所具有的相同地址开始。这经常被用作结构的最后一个成员,在该结构中,当分配n个字节时,该结构被填充。然后,作为最后一个成员的数组可以被索引以访问该填充,而无需指针数学

例如

structfoo
{
INTA;
int b;
charc[0];
};
foo*f=malloc(sizeof(foo)+50);
对于(int i=0;i<50;++i)
f->c[i]=57;
sizeof foo很可能是8,但这并不重要,因为c是该结构的结束地址,而不管该结构是如何字节对齐/填充的


一些Win32 API利用了这一点。

大多数编译器只会将数组设置为具有实际的开始地址,但不会占用任何空间,因此堆栈或结构中的后续变量将从它们在0大小的数组根本不存在时所具有的相同地址开始。这经常被用作结构的最后一个成员,在该结构中,当分配n个字节时,该结构被填充。然后,作为最后一个成员的数组可以被索引以访问该填充,而无需指针数学

例如

structfoo
{
INTA;
int b;
charc[0];
};
foo*f=malloc(sizeof(foo)+50);
对于(int i=0;i<50;++i)
f->c[i]=57;
sizeof foo很可能是8,但这并不重要,因为c是该结构的结束地址,而不管该结构是如何字节对齐/填充的


一些Win32 API利用了这一点。

您遇到了典型的缓冲区溢出问题。虽然定义零大小的数组是不符合要求的,但实际情况是,您在堆栈上得到了一个默认对齐大小的变量(通常为4或8)

因此,当您开始读取该变量时,您将数据放在堆栈上,它开始覆盖堆栈帧。这不是很明显立即,但它破坏了您返回的地址

因此,代码执行read(精细),然后write(精细),然后尝试返回。如果返回地址已被破坏,则会出现分段错误。否则,这种情况可能会继续下去,而不会引起注意。在上一个示例中,您没有得到输出的原因是由于缓冲输出-程序在退出之前没有得到刷新缓冲区的更改(正如从main返回后所做的那样)

下面是一个示例,您如何看到您的代码覆盖了st