bVal is declared in C as an unsigned integer at the default width, typically 4-bytes (or 2-bytes, depending on the system), not 1-byte. So I'd expect you'd declare it as U (for the default width), not U1. Similarly for i2cReg.

C automatically (and obligatorily) promotes single-byte arguments to the default width, when pushing them onto the function call stack, as the receiving function expects. That function then chooses to ignore the "extra" C-generated bits beyond the first 8 as part of its semantics.

Hmm. U1 gives you range checking on the APL side. This feels more like a problem with sign extension as it goes from 1 byte to 4. I will log an issue. Since the work around is easy (whilst sacrificing range checking) it might not get high priority.

Priority or not, I was curious. I tried testing a simple C routine that expected an unsigned (i.e. a 4-byte unsigned even if only one byte matters to the C program/mer), as in the standard declaration you (Ray) showed. The only difference was it reported to me what it saw.

When I did the ⎕NA with U1, the unsigned on the APL side (let's call that number UNS) came across to the C language side as a non-random garbage number, when UNS exceeded 127. (It was fine when unsigned at 127 or less.) This was the number, based on UNS:

4294967168 + 128|UNS -- when 128 ≤ UNS ≤ 255 UNS -- when UNS ≤ 127

4294967168 just happens to be this in binary:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0

(7 zero bits, rather than 8). Looks like a mask for dealing with 7-bit ASCII...

If I then cut it back to 1 BYTE on the C size (UNS&0XFF), it was the correct number.

So, I think there IS a problem in how it handles unsigned numbers between 128 and 255, but since the routine on the other end REQUIRES a 4-byte unsigned, I'm still thinking U is the right pedagogical choice. But perhaps Dyalog APL protects the user beyond what is documented, by quietly extending short items (U1, U2, etc.) put on the call stack. That would be good to see documented (I couldn't find any examples demonstrating implicit expansion in the Lang Ref). Now I'm just curious.

In any case, as you (Geoff) noted, U always works-- no garbage in or out, albeit without APL doing any range checking for integer types.