如何将值保存到已分配内存的指针?

时间:2018-09-02 20:05:28

标签: c

我编写了以下代码:

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

char * convertToBinary(int baseTenNumber)
{
    int counter = 0;    
    char *result = NULL;
    int remainder = baseTenNumber;
    while(remainder)
    {
        result = (char *) realloc(result, sizeof(char) + 2);
        printf("%d\n", baseTenNumber);
        result[counter] = baseTenNumber%2;
        remainder/=2;
        counter++;
    }

    return result;
}

int main (void)
{
    int input = -1;

    while(input)
    {
        printf("Enter an integer: ");
        scanf("%d", &input);
        char * result = convertToBinary(input);
        printf("The binary version of %d is %s\n", input, result);

        memset(result, '0', sizeof(result));
        free(result);
    }


    return 0;
}

是的,我知道二进制文件将被反向写入,稍后将进行介绍。 但是为什么该程序不保存我的值?

我正在尝试在循环的每次迭代中分配内存。我对一次性完成所有操作不感兴趣。

任何提示都会很棒,谢谢!

3 个答案:

答案 0 :(得分:2)

有几种方法可以使内存完全适合C。

一种方法是准确地预先计算所需的内存量,您可以在此处执行此操作。但这并不总是可能的,它需要编写更多的代码,更多的错误以及更多的运行时。

另一种方法是使用var GerenciaBD GERENCIABD var PontoExecucao int GerenciaBD.F_GERENCIABD_ABRIR_CONEXAO_MYSQL() GerenciaBD.DataBase.ExecContext(context.TODO(),"call PESSOA_TESTE", sql.Named("psaida", sql.Out{Dest:&PontoExecucao})) println(PontoExecucao) 。重新分配会变得杂乱且昂贵,这是邀请错误的好方法。如果您要处理现有的大量内存,例如增加数组,那么有时这是必需的。

另一种方法是分配足够大的堆栈缓冲区以容纳任何可能的值,然后使用strdup将其复制到恰好正确的堆内存量。当您需要一次处理所有事物并且不确定大小可能会很棒。例如,从文件读取。

realloc

我们可以为您的问题做同样的事情。

// Allocate a big, reusable buffer
char line[BUFSIZ];
while( fgets(line, sizeof(line), fp) ){
    ...now you can slice and dice line...
}

堆栈内存便宜并且可以快速分配和丢弃。这比一次又一次地重新分配堆内存快得多。使用#include <stdio.h> #include <string.h> // The largest possible string to hold a binary integer #define BINARY_INT_SIZE ((sizeof(int)*8) + 1) // A cheap way to convert from integer 0/1 to char 0/1 const char BINARY_TO_CHAR[] = {'0', '1'}; char * convertToBinary(int number) { // Initialize the stack variable to hold the conversion char result[BINARY_INT_SIZE] = {0}; for( int counter = 0; number; counter++ ) { printf("%d %d %d\n", counter, number, number % 2); result[counter] = BINARY_TO_CHAR[number % 2]; number/=2; } // Copy from the stack into exactly enough heap memory return strdup(result); } 可确保持久堆内存紧凑。

答案 1 :(得分:2)

仅添加到已经给出的精彩答案中,但是我想澄清一些事情,只是为了安全起见,没有人明确指出。

对于初学者来说,您的值会被保存(尽管数量不正确,不在正确的位置,也没有正确的值,我将在后面解释)。您的printf()语句根本无法识别存储在所创建数组的每个索引中的值。在格式字符串中,您使用的是%s格式说明符。如果您实际上正在打印人类可读的ASCII码,则可以。问题是您正在打印文字值01,它们分别映射到“ NULL”和“ heading of heading”。

其他答案对于如何将数字值映射到 ASCII值提出了很好的建议,但是从理论上讲,如果您想在自己的计算机上打印索引按原样排列数组,您将需要通过以下方式进行打印:

printf("The binary version of %d is ", input); for(int i = numDigits - 1; i >= 0; --i) printf("%d", result[i]);

在这种情况下,您要以数字而不是字符的形式打印数组中的每个项目。

接下来我要指出的是您在while循环中的逻辑。您对result[counter]的分配始终为baseTenNum % 2,因此根据数字是始终是偶数还是奇数,它将存储全0或全1。然后,最重要的是,realloc()总是将大小调整为固定大小,而不是随每个新字符一起增长(在另一个答案中指出:-)。

希望这些帮助可以帮助您解决一些麻烦!

答案 2 :(得分:1)

Schwerm的答案是最好的。
如果要在每次迭代中分配内存,则realloc(result, counter + 2)将随着counter的增加而再分配一个字节。 +2为当前字符提供一个字节,为终止符提供一个字节。
要将模运算中的1和0转换为可以打印的字符,请添加'0'

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

char * convertToBinary(unsigned int baseTenNumber)
{
    int counter = 0;
    char *result = NULL;
    char *temp = NULL;
    int remainder = baseTenNumber;
    while(remainder)
    {
        if ( NULL == ( temp = realloc(result, counter + 2))) {
            fprintf ( stderr, "problem realloc\n");
            exit ( 0);
        }
        result = temp;
        printf("%d\n", remainder);
        result[counter] = remainder%2 + '0';
        remainder/=2;
        counter++;
    }
    result[counter] = 0;//terminate
    return result;
}

int main (void)
{
    unsigned int input = 0;

    do
    {
        printf("Enter an integer: ");
        scanf("%u", &input);
        if ( input) {
            char * result = convertToBinary(input);
            printf("The binary version of %d is %s\n", input, result);

            free(result);
        }
    } while(input);

    return 0;
}