You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无编译错误但结果异常:如何安全将long转为unsigned short int?

Safe Conversion from long to unsigned short for Hexadecimal Strings

Alright, let's break down your problem and fix this properly. First, I notice two critical issues in your current code that are likely causing unexpected results:

  1. You're using strtol with a base of 10, but you need to parse hexadecimal strings (base 16).
  2. You're casting a long to unsigned short without checking if the value fits in the smaller type—this leads to silent truncation if the number is too large, which is almost certainly your bug.

Core Principles for Safe Conversion

To safely convert a parsed numeric value to unsigned short, you need to:

  • Parse the string with the correct base (16 for hex)
  • Validate that the parsed value falls within the entire range of unsigned short (0 to USHRT_MAX, defined in <limits.h>)
  • Only cast once you've confirmed the value fits

This uses strtoul (unsigned long conversion) which is more appropriate for hexadecimal values (since hex is almost always used for unsigned data):

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

unsigned short int str_to_bin(char* instr_bin_str) {
    unsigned short int result = 0;
    unsigned long parsed_value;
    char* end_ptr;

    // Parse the input string as UNSIGNED hexadecimal
    parsed_value = strtoul(instr_bin_str, &end_ptr, 16);

    // Check for parsing errors: no valid characters found, or leftover invalid characters
    if (end_ptr == instr_bin_str || *end_ptr != '\0') {
        fprintf(stderr, "error: str_to_bin() - invalid hexadecimal string\n");
        return 6;
    }

    // Check if the parsed value exceeds the maximum size of unsigned short
    if (parsed_value > USHRT_MAX) {
        fprintf(stderr, "error6: str_to_bin() - value too large (max allowed: %u)\n", USHRT_MAX);
        return 6;
    }

    // Safe cast: we've confirmed the value fits
    result = (unsigned short int)parsed_value;
    return result;
}

Why This Works

  • Correct Parsing: Using base 16 ensures hex characters (0-9, A-F/a-f) are interpreted correctly, which fixes the first major issue in your original code.
  • Range Validation: By checking against USHRT_MAX, we avoid silent truncation. If the input value is too big (e.g., 0x10000 which is 65536, just above the 16-bit unsigned short max of 65535), we explicitly error instead of returning a wrong value.
  • Unsigned Parsing: strtoul handles unsigned values natively, so we don't have to worry about negative numbers (which don't make sense for hex in this context).

If You Must Use strtol (Signed Long)

If you need to stick with strtol for some reason, add a check for negative values (since unsigned short can't hold negatives):

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

unsigned short int str_to_bin(char* instr_bin_str) {
    unsigned short int result = 0;
    long parsed_value;
    char* end_ptr;

    parsed_value = strtol(instr_bin_str, &end_ptr, 16);

    if (end_ptr == instr_bin_str || *end_ptr != '\0') {
        fprintf(stderr, "error: str_to_bin() - invalid hexadecimal string\n");
        return 6;
    }

    // Check for negative values AND overflow
    if (parsed_value < 0 || parsed_value > USHRT_MAX) {
        fprintf(stderr, "error6: str_to_bin() - value out of unsigned short range\n");
        return 6;
    }

    result = (unsigned short int)parsed_value;
    return result;
}

Key Takeaways

  • Never cast a larger numeric type to a smaller one without validating the value fits first—silent truncation is a common source of hard-to-debug bugs.
  • Use the right parsing function: strtoul for unsigned values (like hex), strtol for signed decimal values.
  • Always validate the parsing result (check if the entire string was parsed, no invalid characters).

内容的提问来源于stack exchange,提问作者user9135060

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:03:38