I am trying to create a switch on a 32-bit signed integer returned from a C function. This is all being compiled for a 32-bit arm system via: GOARCH=arm GOOS=linux CC="..." go build
My code is:
func ResultToString(value C.int) error {
switch int(value) {
case 1:
return nil
case -1:
return fmt.Errorf("Unknown")
case 0xF3210123:
return fmt.Errorf("Line high")
}
return fmt.Errorf("bad value")
}
The error I am receiving is: pkg/app/conversions.go:200:7: 0xF3210123 (untyped int constant 4079026467) overflows int
0xF3210123
in decimal is 4_079_026_467
and fits completely in 32-bits as 1111 0011 0010 0001 0000 0001 0010 0011
. However, this is the unsigned representation, when I want the signed one (which is -215_940_829
).
I have tried to convert it in the switch but all my methods are not working (here tried on constant 0xF3210124
:
case int(0xF3210124):
gives errorcannot convert 0xF3210124 (untyped int constant 4079026468) to type int
I've also tried creating it as a regular var
and casting that way as described in this blog post: https://go.dev/blog/constants but that isn't working either:
# Source
var testVal = 0xF3210123
...
case int(testVal):
# Error
cannot use 0xF3210123 (untyped int constant 4079026467) as int value in variable declaration (overflows)
I want to use the literals directly to match the specification I am trying to implement. Is there a way to do this easily that I'm just missing?
--
What DOES work is using the converted constant (shown below). However, I have a lot of these codes and again want to use the hex literal for easy spec matching.
# Working example
func ResultToString(value C.int) error {
switch int(value) {
case 1:
return nil
case -1:
return fmt.Errorf("Unknown")
case -215_940_829:
return fmt.Errorf("Line high")
}
return fmt.Errorf("bad value")
}
CodePudding user response:
This might be explained with a particular interpretation of the language spec about untyped constants. It looks like 0xF3210123
is interpreted as an uint32
value, which then causes overflow when converted to a int32
value at compile time.
But it does not do that when converted at runtime.
So ugly, but a workaround could be (i did not test this on a 32-bit system):
var v = 0xF3210124
var x = int32(v)
...
switch ... {
case x: ...
}
CodePudding user response:
I also tried a few things... this one worked:
const (
ZERO int32 = 0
BIG1 = 0xF3210123
BIG2 = 0xFF00FF00
)
and later:
case BIG1:
fmt.Printf("big\n");
It sounds like you'll have to come up with lots of names, but some folks would say that's better than having lots of unknown constants everywhere.