Programming languages 为什么禁止嵌套注释? 为什么在C++中嵌套注释被禁止,java的事实是嵌套注释有用、整洁、优雅,可以用来注释有注释的语句?

Programming languages 为什么禁止嵌套注释? 为什么在C++中嵌套注释被禁止,java的事实是嵌套注释有用、整洁、优雅,可以用来注释有注释的语句?,programming-languages,comments,language-features,Programming Languages,Comments,Language Features,符合/兼容C.< /P> < P>至少C++,这只是部分正确,没有问题: /* // // */ 然而,如果你已经在你想注释掉的部分中得到了一个/*注释,你可能可以用#if 0来进行注释,我认为很多编译器都会对它进行优化。例如: #if 0 /* */ #endif C和C++为简化分析做了。这样,当它们到达/*的注释开头时,解析器可以轻松地扫描到末尾。否则,它必须设置并维护一个堆栈,如果注释标记不匹配,则报告错误 至于为什么java做它,答案很简单——java的语法是用来模仿C++和C

符合/兼容C.< /P> < P>至少C++,这只是部分正确,没有问题:

/*
//
//
*/
然而,如果你已经在你想注释掉的部分中得到了一个/*注释,你可能可以用
#if 0
来进行注释,我认为很多编译器都会对它进行优化。例如:

#if 0
/*

*/
#endif

C和C++为简化分析做了。这样,当它们到达/*的注释开头时,解析器可以轻松地扫描到末尾。否则,它必须设置并维护一个堆栈,如果注释标记不匹配,则报告错误


至于为什么java做它,答案很简单——java的语法是用来模仿C++和C++的。如果允许嵌套评论,可能会让一些C程序员绊倒,并会写很多愤怒的博客帖子

每种语言(-family)都不同,但一般来说,它们不是“禁止”的,只是不受支持。支持它们是一种设计选择

选择(对于较旧的语言)的一个原因可能是易于解析


注:我记得一个C++编译器,它是一个让它们嵌套的选项。它被标记为“非标准”。请考虑以下示例:

/* This is a comment /* Nested Comments */ are not allowed. */
任何介于
/*
*/
之间的内容都被视为注释。在上面的示例中,从
这个
注释
所有内容都被视为注释,包括
/*
。 因此,
是不允许的*/不在注释中。
这是一个不正确的C语句错误

考虑这个例子:

// This is an /* valid */ comment

/
后面的行中的任何内容都将被视为注释。由于
/*valid*/
位于
/
之后的同一行,因此它被视为注释的一部分。

在允许任意长度注释的语言中,程序员很容易意外地注释掉,或者在某些罕见的情况下,“取消注释”返回的代码比所需的代码多或少。在许多情况下,这些错误会导致编译错误,但在其他情况下,它们可能会导致代码被破坏。使用现代语法突出显示编辑器,每个
/*
将增加嵌套注释计数器和每个
*/
将减少注释计数器的规则可能不会引起太多麻烦,但如果没有语法突出显示,即使试图找出哪些代码被注释,哪些代码没有注释,也可能是一个非常令人头痛的问题


如果要从头开始设计语言,一个好的方法可能是指定注释开始和注释结束标记(包括可选字符串),并让语言强制要求注释结束标记中的字符串必须与其相应注释开始标记中的字符串相匹配。假设语法是
,那么编译器可以接受
,但拒绝
。即使人们倾向于使用
#if
指令而不是注释,附加标记以确保每个结束指令与预期的开始指令匹配的功能也会很有用。

问题在于不能简单地“跳过”块。块内部有未知数量的块,因此为了知道该块何时完成,您不能使用常规语言,您必须使用堆栈并遍历每个块,直到堆栈为空,此时您知道该块已完成

不能跳过块的原因是,块的正则表达式只能将/*与“第一个*/it sees after”或“最后一个*/it sees after”或“第n个*/it sees after”匹配

如果我们使用看到的第一个“*/”标记,我们可能会有如下代码

/*
    /*

    */
    the compiler matched /* with */ and this line and the next one will confuse it.
*/
如果我们使用最后一个“*/”标记,我们就有了代码,编译器将跳过文件中第一个注释和文件结尾最后一个注释之间的内容。在本例中,以下代码将被解析为空字符串

/*
    /* hello, world! */
*/
int main(int argc, char ** argv) {
    return 0;
}
/* end of file */
我们不能使用第三个选项跳过n个内部块,而不强制所有注释都具有精确的深度,否则它将找不到内部注释,并且会混淆

实际上,还有第四个选项明确说明注释可以是单个注释、2范围注释、3范围注释等;但是这样做很难看,每个深度级别都需要一个更长的表达式,而且这种方法将注释限制在特定的深度,可能适合某些人,而不适合其他人:如果注释掉一个已经注释掉3次的代码怎么办

通用解决方案可通过预处理器实现,例如:

<?php
function stripComments($code) {
    $stack = array();
    $codeOut = '';
    $stringStream = fopen('php://memory', 'r+');
    fwrite($stringStream, $code);  
    rewind($stringStream);  

    while (!feof($stringStream)) {
        $ch = fgetc($stringStream);

        $nextChar = fgetc($stringStream);
        if ($nextChar === false) {
            break;
        }

        if ($ch == '/' && $nextChar == '*') {
            array_push($stack, '/*');          
        } else if ($ch == '*' && $nextChar == '/') {
            if (count($stack) > 0) {
                array_pop($stack);
            } else {
                die('cannot pop from empty stack');
            }
        } else {
            if (count($stack) == 0) {
                $codeOut .= $ch;
                fseek($stringStream, -1, SEEK_CUR);
            }
        }               

        $prevChar = $ch;
    }
    return $codeOut;
};
?>
这没有考虑引号内的
/**/
块,需要一个稍微复杂一些的堆栈来区分“/*”范围和“\”范围

注释中包含注释的好处是,您可以注释掉包含注释的块,而无需手动剥离注释,这对于每行都有注释的块来说尤其令人沮丧


摘要:这是可以做到的,但大多数语言不希望将注释视为自己的作用域,因为解析注释需要更多的努力。

C最初不是只使用//comment符号吗?另外,为什么Java需要符合C标准?@tloach:
/
在C99.C最初用于ly/**/,而Java则有意模仿C(和C++)为了让现有程序员更熟悉它。Conform这个词在这里可能太强了,但我不确定有什么更好。@tloach-no。最初C只有/**/comments-这就是为什么它们被称为C风格的注释。大多数早期的C编译器也允许嵌套它们,许多(例如gcc)仍然可以作为backw
function stripComments($code) {
    return preg_replace('/\/\*[^\*\/]*\*\//', '', $code);
}