Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.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 Is*++*p可接受的语法?_C - Fatal编程技术网

C Is*++*p可接受的语法?

C Is*++*p可接受的语法?,c,C,在K&R第5.10节中,在其类grep函数的示例实现中,有以下几行: while (--argc > 0 && (*++argv)[0] == '-') while (c = *++argv[0]) 理解那里的语法对我来说是最具挑战性的事情之一,即使是在第一次看了几周之后,我仍然必须非常缓慢地思考语法才能理解它。我用这种替代语法编译了这个程序,但我不确定第二行是否允许。我从来没有见过像这样交错的*和++,但对我来说,这很有意义,它可以编译并运行。它也不需要括号或括

在K&R第5.10节中,在其类
grep
函数的示例实现中,有以下几行:

while (--argc > 0 && (*++argv)[0] == '-')
    while (c = *++argv[0])
理解那里的语法对我来说是最具挑战性的事情之一,即使是在第一次看了几周之后,我仍然必须非常缓慢地思考语法才能理解它。我用这种替代语法编译了这个程序,但我不确定第二行是否允许。我从来没有见过像这样交错的
*
++
,但对我来说,这很有意义,它可以编译并运行。它也不需要括号或括号,这也许是为什么我觉得它更清楚的一部分。我只是从一个方向(从右到左)读取操作符,而不是在变量名的任一侧来回跳转

while (--argc > 0 && **++argv == '-')
    while (c = *++*argv)

首先,这是一种让所有阅读你代码的人都去的方法,哈

因此,从可读性的角度来看,不,您可能不应该编写这样的代码

尽管如此,它仍然是有效的代码,分解如下:

*(++(*p))
首先,
p
被取消引用。然后它是递增的。然后再次取消引用


更糟糕的是,这一行:

while (c = *++*argv)

在循环条件中具有赋值。所以现在你有两个副作用让你的读者头晕目眩。耶

对我来说似乎有效。当然,您不应该从左到右阅读它,这不是C编译器解析源代码的方式,也不是C语言语法的工作方式。根据经验,您应该首先找到要对其进行操作的对象(在本例中为-
argv
),然后分析操作符,通常像本例中那样,从内部(对象)到外部。当然,实际的解析(和读取)规则更加复杂


另外,就我个人而言,我认为这一行代码真的不难理解(而且我不是C编程大师),所以我不认为你应该像神秘主义者建议的那样用括号括起来。如果你知道我的意思的话,那只会让代码看起来更大…

没有歧义,即使不知道优先级规则

++
*
都是前缀一元运算符;它们只能应用于它们后面的操作数。第二个
*
只能应用于
argv
++
*argv
,第一个
*
++*argv
。所以它相当于
*(++(*argv))
。在
++
*
的先例之间没有可能的关系,这可能意味着其他任何东西

这与
*argv++
不同,后者可能是
(*argv++
*(argv++)
,您必须应用优先级规则来确定哪个(它是*(argv++)`因为后缀运算符比前缀一元运算符绑定得更紧密)


有一个约束,
++
只能应用于左值;因为
*argv
是左值,所以这不是问题。

此代码有效吗?是的,但那不是你要的

这个代码可以接受吗?这取决于(谁能接受?)

我不认为这是可以接受的。我认为这是“比必要的阅读更难”的原因。 第一,;许多程序员必须使用几种不同的语言,可能使用不同的运算符优先级规则。如果您的代码看起来依赖于特定语言的运算符优先级规则(即使它不依赖),那么人们必须停止并尝试记住哪些规则适用于哪种语言

第二;不同的程序员有不同的技能水平。如果你曾经在一个庞大的开发团队中工作,你会发现最好的程序员编写的代码大家都能理解,而最差的程序员编写的代码包含团队中一半人无法发现的细微错误。大多数C程序员应该理解“
*++*argv
”,但是一个好的程序员知道少数“不太好”的程序员要么不理解它,要么需要一段时间才能理解它


第三;在所有不同的写作方式中,你应该选择最能表达你意图的变体。对于这段代码,您使用的是一个数组,因此它看起来应该是一个数组(而不是指针)。注意:出于同样的原因,“
uint32\u t foo=0x00000002;
”比“
uint32\u t foo=0x02;
”更好。

在我看来像是未定义的行为。稍微更正一下<代码>argv[0]应为常量IMHO。也就是说,
argv
是一个非常量的函数参数,但它指向字符串指针的只读数组。除此之外,对于熟练的C/C++来说,语法还可以programmer@PrasoonSaurav:它有什么未定义的?@valdo:标准明确规定,
argc
argv
以及
argv
数组指向的字符串是可修改的。奇怪的是,它并没有说
argv
数组的元素是可修改的(或者它们不是)。我不知道这个省略是否是故意的,但它在C11中没有改变。酷,我就是这么想的。我没有很多阅读代码的经验,所以我不知道它有多普遍,也不知道它是否会让人困惑。但我不认为这会让人困惑,因为这些操作符的关联性是从右到左的。像你那样使用括号可能很好,但这有点像说((4+5)+7)=16,不是吗?不管怎样,对我来说都不是特别重要,我也不想争辩。。。只是大声思考。:-)如果你停下来仔细阅读,就不会那么困惑了。但这是非常罕见的(我以前从未见过),更不用说奇怪的符号组合看起来会很尴尬。(让我想起
x-->0
)@1111:你必须问这个问题。也就是说