制作 os 时按引用传递错误

Error passing by reference when making os

我正在制作一个 os 并且已经启动到一个用 c 制作的 64 位内核。我已经制作了一个正在运行的打印函数,并且正在尝试制作一个将十六进制值转换为字符串的函数,以便我可以打印它们。我的代码导致引导循环,但是当我在 linux 中正常将完全相同的代码编译为 运行 时,它运行良好。相关代码:

int logarithm(double value, int base, int* output) {
    int i = 0;

    while (value > 1) {
        value /= base;
        i++;
    }

    *output = i;
}

int power(int value, int power, int* output) {
    if (power == 0) {
        value = 1;
    } else {
        for (int i = 0; i < (power - 1); i++) {
            value *= value;
        }
    }

    *output = value;
}

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 0;
    logarithm((double)hex, 16, &hexLength);
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i++) {
        power(16, i, &powerValue);
        output[hexLength - i - 1] = (hex & (powerValue * 15)) / powerValue + '0';
    }

    *string = output;
}

如果我将 hexToStr() 函数代码更改为此(通过对字符串的硬编码值消除对 logarithm() 和 power() 函数的需要),它在 linux 和我的内核中都有效:

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 10;
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i++) {
        output[hexLength - i - 1] = 'A';
    }

    *string = output;
}

关于为什么会发生这种情况有什么建议吗?

提供的代码调用了未定义的行为。例如让我们考虑这个函数

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 10;
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i++) {
        output[hexLength - i - 1] = 'A';
    }

    *string = output;
}

在这个赋值语句中:

    output[hexLength] = 0;

由于索引的有效范围为[0, hexLength).

,数组外有写入数据

或者函数通过引用局部数组output设置一个传递给函数的指针,退出函数后不会存活。因此 returned 指针将具有无效值。

另一个例子当参数value等于3且参数power等于3时函数power的结果值由于此 for 循环中的赋值语句,将等于 81 而不是 27

    for (int i = 0; i < (power - 1); i++) {
        value *= value;
    }

此外,函数 return 什么都没有,尽管它的 return 类型不是 void。

int power(int value, int power, int* output) {

还有这个表情

(hex & (powerValue * 15)) / powerValue + '0'

没有意义。

需要启用 SSE 单元才能使用浮点数和双精度数。以及更改值的传回方式。工作代码:

void log(float value, float base, uint64_t* output) {
    uint64_t i = 0;

    while (value >= 1) {
        value /= base;
        i++;
    }

    *output = i;
}

void pow(uint64_t value, uint64_t exponent, uint64_t* output) {
    uint64_t result = 1;

    for (uint64_t i = 0; i < exponent; i++) {
        result = result * value;
    }

    *output = result;
}

void hexToStr(uint64_t hex, char* output) {
    uint8_t hexLen = 16;
    log((float)hex, (float)16, &hexLen);
    char result[hexLen + 3];
    result[0] = '0';
    result[1] = 'x';
    result[hexLen + 2] = 0;

    uint64_t powerValue = 1;
    for (uint8_t i = 0; i < hexLen; i++) {
        pow(16, i, &powerValue);
        result[hexLen - i + 1] = (hex & (uint64_t)(powerValue * (uint64_t)15)) / powerValue + '0';
    }

    for (uint8_t i = 0; i < hexLen + 3; i++) {
        switch(result[i]) {
            case ':':
                result[i] = 'A';
                break;
            case ';':
                result[i] = 'B';
                break;
            case '<':
                result[i] = 'C';
                break;
            case '=':
                result[i] = 'D';
                break;
            case '>':
                result[i] = 'E';
                break;
            case '?':
                result[i] = 'F';
                break;
        }
        output[i] = result[i];
    }
}