путаница по поводу преобразования `uint8` в` int8` - PullRequest
4 голосов
/ 17 апреля 2019

Я хочу преобразовать uint8 в int, поэтому я пишу const 0xfc и пытаюсь использовать int8(0xfc) для его преобразования. Однако код вызывает ошибку:

package main

import (
    "fmt"
)

func main() {
    a := int8(0xfc)  // compile error: constant 252 overflows int8
    b := a
    fmt.Println(b)
}

Но если я отложу преобразование типов после присваивания, код может обойтись.

package main

import (
    "fmt"
)

func main() {
    a := 0xfc
    b := int8(a)  // ok
    fmt.Println(b)
}

Мой вопрос:

  • Есть ли разница между этими двумя кодами?
  • Почему первый вызывает ошибку компиляции?

Ответы [ 2 ]

5 голосов
/ 17 апреля 2019
  1. см .: https://golang.org/ref/spec#Constant_expressions

Значения типизированных констант всегда должны быть точно представлены значениями типа константы. Следующие константные выражения недопустимы:

uint(-1)     // -1 cannot be represented as a uint
int(3.14)    // 3.14 cannot be represented as an int
int64(Huge)  // 1267650600228229401496703205376 cannot be represented as an int64
Four * 300   // operand 300 cannot be represented as an int8 (type of Four)
Four * 100   // product 400 cannot be represented as an int8 (type of Four)
  1. см: https://blog.golang.org/constants

не все целочисленные значения могут вписываться во все целочисленные типы. Могут возникнуть две проблемы: значение может быть слишком большим или отрицательное значение, назначаемое целому типу без знака. Например, int8 имеет диапазон от -128 до 127, поэтому константы вне этого диапазона никогда не могут быть назначены переменной типа int8:
var i8 int8 = 128 // Error: too large.
Аналогично, uint8, также известный как byte, имеет диапазон от 0 до 255, поэтому большая или отрицательная постоянная не может быть назначена для uint8:
var u8 uint8 = -1 // Error: negative value.
Эта проверка типов может выявить ошибки, подобные этой:

    type Char byte
    var c Char = '世' // Error: '世' has value 0x4e16, too large. 

Если компилятор жалуется на использование вами константы, вероятно, это настоящая ошибка, подобная этой.


Мое реальное требование - преобразовать byte в int32 при разборе двоичного файла. Я могу встретить постоянный байт 0xfc, и я должен передать его в int8 перед преобразованием в int32 с учетом знака.

Да, это путь:


    var b byte = 0xff
    i32 := int32(int8(b))
    fmt.Println(i32) // -1
2 голосов
/ 17 апреля 2019

Есть ли разница между этими двумя кодами?

В первом примере используется константное выражение .Второй использует простые выражения.Выражения констант оцениваются во время компиляции по правилам, отличным от простых выражений.

Почему первый вызывает ошибку компиляции?

int8(0xfc) является типизированным константным выражением .Значения типизированных констант всегда должны быть точно представлены значениями константного типа.Компилятор сообщает об ошибке, поскольку значение 252 не может быть представлено значениями int8.

Основываясь на комментариях к другим ответам, я вижу, что цель состоит в том, чтобы получить int32 из байта с расширением знака.Для байтовой переменной b используйте выражение int32(int8(b)), чтобы получить значение int32 с расширением знака.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...