Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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
Java 为什么常量(字符)上的xor操作在使用变量时工作方式不同_Java_C#_C++_C_Expression - Fatal编程技术网

Java 为什么常量(字符)上的xor操作在使用变量时工作方式不同

Java 为什么常量(字符)上的xor操作在使用变量时工作方式不同,java,c#,c++,c,expression,Java,C#,C++,C,Expression,请查看以下代码: 案例1: 它工作得很好。 但当我使用变量而不是常量时,如下所示: 案例2: 在java语言中:案例1起作用,a的值为1,但案例2不起作用 在C和C++中:两种情况都是有效的,A值为1<P/P。 在C中:两种情况都不起作用 在javascript中:这两种情况都有效,这不是HLL,a的值为0 我知道java正在将变量转换为整数以进行二进制操作,但为什么它在案例1中有效而在案例2中无效,为什么同样的方法在C#中无效,以及为什么javascript中的值不同 更新 当我将变量设置为

请查看以下代码:

案例1:

它工作得很好。 但当我使用变量而不是常量时,如下所示:

案例2:

在java语言中:案例1起作用,a的值为1,但案例2不起作用

在C和C++中:两种情况都是有效的,A值为1<P/P。 在C中:两种情况都不起作用

在javascript中:这两种情况都有效,这不是HLL,a的值为0


我知道java正在将变量转换为整数以进行二进制操作,但为什么它在案例1中有效而在案例2中无效,为什么同样的方法在C#中无效,以及为什么javascript中的值不同

更新 当我将变量设置为final时,它在java中的效果比在C#中的效果要好

但我仍然无法理解为什么常数是有效的,但当使用变量时,它们不是。以及为什么其他高级编程语言不会发生同样的情况。
我认为这是一个基本的操作,应该以相同的行为在所有编程语言中工作

注意:为了在javascript中测试上述所有情况,我在所有情况下都将“char”替换为“var”,并且它们都正常工作


只回答Java

表达式
'x'^'y'
是a
x^y
不是,除非两个变量都声明为
final
。此外,结果是
int
^
是一个,这意味着两个操作数在求值之前都必须是整数类型
char
升级为
int

因此,您有了这个
int
表达式,并尝试将其缩小为
char
。在一般情况下,这可能会导致精度损失(int为4字节,char为2),因此编译器不允许您在没有明确说明它是您想要做的事情(通过转换为
char
)的情况下执行此操作。但是,如果常量表达式的值适合新类型,则可以隐式缩小其范围。发件人:

  • 如果变量的类型为
    字节
    字符
    ,并且常量表达式的值可在变量的类型中表示,则可以使用缩小原语转换
(增加重点)


直觉上,这是完全有道理的:错误是告诉你,你可能会失去精度,所以它希望你确认你知道这一点;从某种意义上说,这是一个响亮的警告。但是,如果编译器完全知道这不会发生,就像对常量表达式一样,那么它会使事情变得更容易,并“隐藏”该警告。

在正常情况下,在执行操作之前,下列二进制运算符的操作数会“加宽”

(摘自)

  • 乘法运算符*、/、和%(§15.17)

  • 数字类型+和-(§15.18.2)的加减运算符

  • 数值比较运算符=(§15.20.1)

  • 数值相等运算符==和!=(§15.21.1)

  • 整数位运算符&、^和|(§15.22.1)

  • 在某些情况下,条件运算符?:(§15.25)

对于
char
操作数,加宽将把操作数转换为
int

对于算术运算和位运算,运算结果的类型与两个操作数的“加宽”相同

x
y
具有type
char
时,表达式
x^y
为您提供一个
int
值。如果没有类型转换,则无法将其分配回
char
,因此会出现编译错误


对于使用
char
literals的情况,同样的加宽过程也会发生。但该语言中有一个“特殊例外”,允许隐式缩小常量表达式的值,前提是常量表达式的值适合该类型。在这种情况下,
'x'^'y'
将“适合”到
字符中,因此允许赋值


<>对于常量表达式的异常,JLS引用是.< /P> < P>我将考虑C语言、C++语言和C语言。 在C#中,没有从整型到char型的隐式转换。根据ECMA 334标准“C#规范”第11.1.5节“整体类型”

•没有从其他类型到字符类型的隐式转换。 特别是,即使sbyte、byte和ushort类型 可使用char类型完全表示的值的范围, 不存在从sbyte、byte或ushort到char的隐式转换

因此,您需要显式地将运算符的结果强制转换为char类型。比如说

using System;

namespace ExclusiveOr
{
    class Program
    {
        static void Main(string[] args)
        {
            char a = ( char )('x' ^ 'y' );
            char c = 'x', d = 'y';
            char b = ( char )( c ^ d );

            Console.WriteLine("a = {0}, b = {1}", (int)a, (int)b);
        }
    }
}
输出是

a = 1, b = 1
根据C标准(第6.7.9节初始化)

4具有静态属性的对象的初始值设定项中的所有表达式 或线程存储持续时间应为常量表达式或字符串 文字

例如,这段代码将被编译

#include <stdio.h>

char a = 'x' ^ 'y';

int main(void) 
{
    printf( "a = %d\n", a );

    return 0;
}
#include <stdio.h>

char c = 'x';
char d = 'y';

char b = c ^ d;

int main(void) 
{
    printf( "b = %d\n", b );

    return 0;
}
但是,不会编译此代码

#include <stdio.h>

char a = 'x' ^ 'y';

int main(void) 
{
    printf( "a = %d\n", a );

    return 0;
}
#include <stdio.h>

char c = 'x';
char d = 'y';

char b = c ^ d;

int main(void) 
{
    printf( "b = %d\n", b );

    return 0;
}

在C++中,对于静态存储时间的对象没有这样的限制,所以所有与上面所示的C程序类似的程序的例子都会被编译。

什么是确切的错误?没有C或C++的RePro?或者,你是指文件/命名空间范围?在这种情况下,仅C的错误:Java的整洁扭曲:如果
x
y
都是
final
,它将编译!这两种情况都适用于c和c++@Bathsheba:反对票可能是因为这个问题太广泛了:对四种不同语言的不同解释。尽管如此,近距离投票会更好。这一推理对C#也是有效的,唯一的区别是ap
a = 1
#include <stdio.h>

char c = 'x';
char d = 'y';

char b = c ^ d;

int main(void) 
{
    printf( "b = %d\n", b );

    return 0;
}
#include <stdio.h>

char c = 'x';
char d = 'y';


int main(void) 
{
    char b = c ^ d;
    printf( "b = %d\n", b );

    return 0;
}
b = 1