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

C语言中通过指针访问char数组仅能获取首字符的问题

C语言指针传递数组后函数内仅能访问第一个字符的问题分析与修复

问题描述

将C语言char数组通过指针传递给函数后,函数内访问该数组时仅能获取第一个字符,其余内容均为随机字节,但调用函数前所有变量状态正常,参考相关方案后问题仍未解决。以下是原代码及运行输出:

原代码

#include <stdio.h>
#include <string.h>
#include <stdint.h>

void hex_to_bytes(char *hex, char **bytes, size_t *bytes_len) {
    int length = strlen(hex) % 2? strlen(hex) + 1 : strlen(hex);
    unsigned char checkedHex[length];
    
    for (int i = 0; i <= length; i++) {
        if (i == 0 && strlen(hex) % 2){
            checkedHex[0] = '0';
        }
        else if (i == length){
            checkedHex[i] = '\x00';
        }
        else {
            checkedHex[i] = hex[i]; 
        } 
    }
    
    *bytes_len = length / 2;
    int counter = 0;
    for (int i = 0; i < length / 2; i++){
        sscanf(&checkedHex[counter], "%2hhx", &bytes[i]);
        counter += 2;
    }
}

void *b64_encode(unsigned char *bytes, size_t bytes_len)
{
    printf("in b64_encode %p\n", bytes);
    printf("bytes = %s\n", &bytes[48]);

    printf("0x");
    for (int i = 0; i < bytes_len; i++) {
        printf("%02X", bytes[i]);
    }
    printf("\n");
}

int main() {
    unsigned char hex[] = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
    unsigned char *bytes[48] = {0};
    size_t bytes_len = 0;

    hex_to_bytes(hex, (unsigned char **) &bytes, &bytes_len);

    printf("in main       %p\n", &bytes);
    printf("bytes = %s\n", &bytes[48]);

    unsigned char *base64 = b64_encode(bytes, bytes_len);
    return 1;
}

原运行输出

in main       0x7ff7b0ef1350
bytes = 49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
in b64_encode 0x7ff7b0ef1350
bytes = l
0x490000000000000027000000000000006D0000000000000020000000000000006B000000000000006900000000000000

问题根源分析

  1. 变量类型定义错误:main函数中unsigned char *bytes[48]是指针数组(每个元素是unsigned char*类型),但实际需要的是存储转换后字节的字符数组,类型不匹配导致后续内存操作完全偏离预期。
  2. 强制转换导致内存操作异常:调用hex_to_bytes时将字符数组地址强制转为unsigned char**,函数内&bytes[i]实际操作的是指针数组元素(64位系统下每个元素占8字节),因此输出出现大量填充的00。
  3. 数组越界访问:hex_to_bytes中checkedHex数组长度为length,但循环条件i <= length会访问checkedHex[length],超出合法下标范围(0~length-1),触发未定义行为。
  4. 函数参数传递错误:调用b64_encode时传递指针数组bytes,但函数期望的是unsigned char*类型的字节数组指针,类型不匹配导致访问异常。

修复后的代码

#include <stdio.h>
#include <string.h>
#include <stdint.h>

void hex_to_bytes(char *hex, unsigned char *bytes, size_t *bytes_len) {
    int hex_len = strlen(hex);
    int length = hex_len % 2 ? hex_len + 1 : hex_len;
    // 定义足够长度的数组存储补0后的十六进制字符串,包含终止符
    unsigned char checkedHex[length + 1] = {0};
    
    if (hex_len % 2) {
        checkedHex[0] = '0';
        memcpy(checkedHex + 1, hex, hex_len);
    } else {
        memcpy(checkedHex, hex, hex_len);
    }
    
    *bytes_len = length / 2;
    int counter = 0;
    for (int i = 0; i < *bytes_len; i++) {
        sscanf(&checkedHex[counter], "%2hhx", &bytes[i]);
        counter += 2;
    }
}

void *b64_encode(unsigned char *bytes, size_t bytes_len)
{
    printf("in b64_encode %p\n", bytes);
    // 字节数组不是字符串,直接用%s输出会因终止符提前结束,改为打印单个字节的十六进制值
    printf("bytes[48] = 0x%02X\n", bytes[48]);

    printf("0x");
    for (int i = 0; i < bytes_len; i++) {
        printf("%02X", bytes[i]);
    }
    printf("\n");
    return NULL; // 补充返回值避免编译警告
}

int main() {
    unsigned char hex[] = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
    // 定义字符数组存储转换后的字节,长度足够容纳结果
    unsigned char bytes[48] = {0};
    size_t bytes_len = 0;

    // 直接传递字节数组地址,无需强制转换
    hex_to_bytes((char*)hex, bytes, &bytes_len);

    printf("in main       %p\n", bytes);
    printf("bytes[48] = 0x%02X\n", bytes[48]);

    unsigned char *base64 = b64_encode(bytes, bytes_len);
    return 0;
}

关键修改说明

  • 将main中的unsigned char *bytes[48]改为unsigned char bytes[48],定义为字节数组而非指针数组。
  • 修改hex_to_bytes的参数类型为unsigned char *bytes,直接接收字节数组指针,删除不必要的二级指针和强制转换。
  • 修复checkedHex的数组越界问题,定义长度为length+1并初始化,用memcpy替代手动循环复制,避免错误。
  • 修正b64_encode中字节数组的输出方式,字节数组不是字符串,不能直接用%s输出,改为打印单个字节的十六进制值。
  • 补充b64_encode的返回值,避免编译警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:54:53