为啥在三元函数中分配给数组类型的表达式失败

Posted

技术标签:

【中文标题】为啥在三元函数中分配给数组类型的表达式失败【英文标题】:why is assignment to expression with array type failed in ternary function为什么在三元函数中分配给数组类型的表达式失败 【发布时间】:2021-12-09 02:47:52 【问题描述】:

这个程序我用不同的方式写了很多次,但我没有得到输出,也无法找出错误,有没有人能指出这个程序中的逻辑错误?

#include<stdio.h>
#include<string.h>

int main()

    float temp;
    char c[15]; 
    
    printf("Enter temperature in F degree=");
    scanf("%f",&temp);
    
    c = (temp>=80    ? strcpy(c,"swimming"):
        (60<=temp<80 ? strcpy(c,"tennis"):
        (40<=temp<60 ? strcpy(c,"Golf"):
                       strcpy(c,"skiing 1."))));    
    
    printf("%s",c);

【问题讨论】:

你不能给数组赋值。只需删除c =。但是这种代码很糟糕。对于这个用例,只要坚持使用旧的 if/else。 忘掉三元,问问自己这会做什么:c = strcpy(c,"swimming") 不要像那样滥用?: 运算符。使用旧的 if/else,你的代码会更清晰。而60&lt;=temp&lt;80 很可能不会做你想做的事。比较运算符不会在 C 中链接。 60&lt;=temp&lt;80 这可能不符合您的预期。 temp&gt;=80 已经评估为假时,您不必检查temp&lt;80 是否。 【参考方案1】:

您不能将任何内容分配给c。 C 中的数组衰减为指向其第一个元素的指针。 = 运算符的左操作数也会发生这种情况。 而且这样的指针不是 L 值。而是像1+1foo(1)&amp;c(int)c 这样的临时计算结果。

R 值不指定对象,因此无法分配。

来自6.3.2.1p3:

除了当它是 sizeof 运算符的操作数时,_Alignof 运算符,或一元 & 运算符,或者是用于 初始化一个数组,一个类型为''array of type''的表达式是 转换为类型为 ''pointer to type'' 的表达式 到数组对象的初始元素并且不是左值。 如果数组对象具有寄存器存储类,则行为是 未定义。

【讨论】:

C 中的数组衰减为指向其第一个元素的指针。这发生在 = 运算符的左操作数上。而且这样的指针不是左值。 IMO 更清楚地说“数组衰减到其第一个元素的 地址”,因为这样可以更好地捕获“不是左值” .您不能为您的房子分配不同的街道地址 - 您的房子就是它所在的位置。与 C 中的数组相同 - 您无法分配其地址,因为数组 具有 一个地址,但指针 拥有 一个地址。这也适用于传递给函数的数组,因为函数参数是左值。【参考方案2】:

数组没有赋值运算符。它们是不可修改的左值。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

    ...可修改的左值是没有数组类型的左值, 没有不完整的类型,没有 const 限定 类型,如果是结构或联合,则没有任何成员 (包括,递归地,所有包含的任何成员或元素 聚合或联合)具有 const 限定类型。

所以代替这个赋值语句

c = (temp>=80    ? strcpy(c,"swimming"):
    (60<=temp<80 ? strcpy(c,"tennis"):
    (40<=temp<60 ? strcpy(c,"Golf"):
                   strcpy(c,"skiing 1.")))); 

您使用了错误的逻辑表达式,例如 60&lt;=temp&lt;80(它始终计算为逻辑真,因为子表达式 60 &lt;= temp 计算结果为整数 01,在任何情况下都小于 80)你应该写

(temp>=80    ? strcpy(c,"swimming"):
    (60<=temp && temp <80 ? strcpy(c,"tennis"):
    (40<=temp && temp <60 ? strcpy(c,"Golf"):
                   strcpy(c,"skiing 1.")))); 

虽然为了可读性,使用 if-else 语句重写此语句会更好

if ( temp>=80 )

    strcpy(c,"swimming");

else if ( temp >= 60 )

    strcpy(c,"tennis");

else if ( temp >= 40 )

    strcpy(c,"Golf");

else

    strcpy(c,"skiing 1.");
 

【讨论】:

最好只使用旧的 if/else 以获得更好的可读性【参考方案3】:

strcpy(即char *)的返回值分配给您的变量c(即char数组)是非法的C代码。

一个简单的if ... else if ... else if ... else ... 在每个块中都有一个strcpy 会是一个更好的解决方案。

如果你真的想要一个单一的代码行,你可以把三元的东西放在strcpy 里面,比如:

strcpy(c, temp >= 80 ? "swimming" : 
          temp >= 60 ? "tennis" : 
          temp >= 40 ? "Golf" : 
          "skiing 1.");

注意:在第二部分中检查temp &gt;= 60 就足够了。您不需要temp &lt; 80,因为之前的temp &gt;= 80 条件已经是这样了。

【讨论】:

【参考方案4】:

您可以分配指针,但不能分配数组。主要的混淆是数组decay指向表达式中的指针。但是指针和数组完全不同。

如果你想分配使用指针。

这里的另一个问题是逻辑表达式。

60&lt;=temp&lt;80 始终为真,因为它等同于 (60&lt;=temp)&lt;80(60&lt;=temp) 将导致 10 并且这些值始终低于 80

#include <stdio.h>
#include <stdlib.h>

int main(void)

    float temp;
    char *c=malloc(15); 
    
    printf("Enter temperature in F degree=");
    scanf("%f",&temp);
    
    c = (temp>=80    ? strcpy(c,"swimming"):
        (60<=temp && temp <80 ? strcpy(c,"tennis"):
        (40<=temp && temp <60 ? strcpy(c,"Golf"):
                       strcpy(c,"skiing 1."))));    
    
    printf("%s",c);

【讨论】:

【参考方案5】:

click for code here您不能为字符串函数返回的字符数组赋值。此字符串函数将值返回到字符串函数中提供的目标字符数组

但是你可以这样使用三元运算符->> 删除这部分 (c =)。并在您编写此代码的所有部分中将此部分从 (4060)。只需编写您要执行的三元运算,然后您的代码就可以工作了。

【讨论】:

请勿发布代码图片。 请将您的代码直接发布到问题中,无需添加将来可能会失效的额外 URL。

以上是关于为啥在三元函数中分配给数组类型的表达式失败的主要内容,如果未能解决你的问题,请参考以下文章

在php中分配给关联数组切片

Python相当于在Matlab中分配给一个数组(在for循环内)

JavaScript - 为啥包含括号会导致三元表达式错误?

匿名函数与三元表达式

从新分配的内存中分配给对象

Python全栈day18(三元运算,列表解析,生成器表达式)