1

On a native build, the following code prints -1. Compiled to WASM and run in node.js, it prints 4294967295. Why are the results different?

#include <iostream>

int main() {
    unsigned F = 20;
    long HB = 19; // both give -1 if this is `long long`
    std::cout << HB-F << std::endl;
    return 0;
}

This is with g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 as the native compiler and em++ 3.1.66 (1f519517284660f4b31ef9b7f921bf6ba66c4041) for emscripten to compile to WASM.

3
  • “Why are the results different?” — They’re not. The web assembly is treating the result as unsigned (but it shouldn’t be, AFAIK). Commented Sep 14, 2024 at 3:54
  • What are the size / range of unsigned and long on each platform? Commented Sep 14, 2024 at 4:00
  • 1
    My recommendation: never use [unsigned] long type on C++ because you never know if it will be 32 or 64-bit. Use instead [u]int32_t or [u]int64_t. Commented Sep 14, 2024 at 15:58

1 Answer 1

2

sizeof(unsigned) == sizeof(long) in WASM like in Windows ABI, and long HB (that has the same size as int) is promoted to unsigned long (which on this platform has the same size as unsigned int).

g++ by default translates the code to a 64-bit binary. In this case sizeof(unsigned) < sizeof(long) and unsigned F is promoted to long int.

Try to invoke g++ with -m32 to get the WASM result.

Sign up to request clarification or add additional context in comments.

17 Comments

Indeed, you are correct, -m32 gives the same result as WASM. But is that also a bug, as suggested by NathanOliver's comment on the question referencing https://timsong-cpp.github.io/cppwp/conv.rank?
@SirNate I retracted my comment because I found this which makes me think the behavior in this case is correct. With the last bullet point of 1.5.3 as the state this example is in.
@MatthewFlaschen Yep, unsigned long: godbolt.org/z/EEd4eo13z
@Peter Reviewing Nathan's arithmetic conversion source ("I found this" above): a. "[NO, continue] If [unsigned] has rank greater than or equal to the rank of [long]. b. [DONE if long is 64-bit and unsigned is 32-bit, continue if both are 32-bit] "Otherwise, if [long] can represent all of the values of [unsigned], C is [long]." c. [C is unsigned long] "Otherwise, C is the unsigned integer type corresponding to S." It appears all mentioned implementations are correct.
@Peter For b./1.5.3.2, "Otherwise, if S can represent all of the values of U, C is S.", the size does matter.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.