One float number prints okay in C, the other doesn't

时间:2021-12-31 14:31:29

The result of running the following:

运行以下内容的结果:

struct drinks{
    float alcohol;
    float price;
    char name[1];
};

/**.com/questions/10162152/how-to-work-with-string-fields-in-a-c-struct*/

void main(){

    struct drinks cosmo;
    //The following:
    cosmo.alcohol = 20.67;
    //gives some crazy result when printed ! Says alcohol content is 2345826759803.00000000 (or any random number like that)
    cosmo.price = 10.0;
    char name[] = "Cosmopolitan";
    size_t length = strlen(name);
    realloc(cosmo.name,length);
    strcpy(cosmo.name, name);

    printf("The alcohol content of the %s is %4.2f, and it costs %2.f",cosmo.name, cosmo.alcohol, cosmo.price);
}

is exactly what it should be (the name and price of the drink print fine!) except that the alcohol content of the drink prints as a ridiculous number!

正是它应该是什么(饮料的名称和价格打印罚款!),除了饮料的酒精含量打印为一个荒谬的数字!

P.s. the theme of the code is nonsense, I'm just learning and decided to come up with anything.

附:代码的主题是无稽之谈,我只是在学习并决定想出任何东西。

EDIT: It worked ! I used the simple fix, thank you ! Can I ask now, and feel free to get technical, why is it that the memory allocation to "name" has any impact on printing the correct float value for the drink's alcohol content ?

编辑:它工作了!我用过简单的修复,谢谢!我现在可以问,并随意获取技术,为什么“名称”的内存分配对打印饮料酒精含量的正确浮动值有什么影响?

3 个解决方案

#1


2  

you have a field name which is a char array of size 1 in your stucture.

你有一个字段名称,它是你的结构中大小为1的字符数组。

You performed a realloc(cosmo.name,length); which is undefined behaviour, which can explain that the numbers are then "ridiculous".

你执行了realloc(cosmo.name,length);这是未定义的行为,可以解释这些数字是“荒谬的”。

Your structure should either define a bigger size for the strings

您的结构应该为字符串定义更大的大小

struct drinks{
float alcohol;
float price;
char name[100];};

or define a pointer (set it to NULL so realloc works, or use malloc):

或定义一个指针(将其设置为NULL,以便realloc工作,或使用malloc):

struct drinks{
float alcohol;
float price;
char *name;};

And when you realloc/malloc, don't forget string terminator (+1) or use strdup

当你realloc / malloc时,不要忘记字符串终结符(+1)或使用strdup

cosmo.name = malloc(1+length);
strcpy(cosmo.name, name);

or

cosmo.name = strdup(name);

#2


2  

There are two problems: The first is that the structures name member is an array which will have a size fixed at the time of compilation. You can not reallocate that. Calling realloc will lead to undefined behavior.

有两个问题:第一个是结构名称成员是一个在编译时具有固定大小的数组。你无法重新分配。调用realloc将导致未定义的行为。

The next problem is that you then copy a to long string into the single-element array thereby writing out of bounds and again have undefined behavior.

接下来的问题是,然后将一个长字符串复制到单元素数组中,从而写出超出边界并再次具有未定义的行为。

The obvious and simple solution is to create the array with a larger size to begin with. You can also turn the name member into a pointer in which case you can allocate memory for it (with malloc or strdup). If you opt for the second solution and use malloc, remember that strings in C have a terminator. So a string like "hello" have six elements: The five you see and which are counted with strlen plus the terminator.

显而易见且简单的解决方案是创建具有更大尺寸的阵列。您还可以将名称成员转换为指针,在这种情况下,您可以为其分配内存(使用malloc或strdup)。如果您选择第二个解决方案并使用malloc,请记住C中的字符串有一个终止符。所以像“你好”这样的字符串有六个元素:你看到的五个元素和用strlen加上终结符计算的元素。

#3


1  

The correct way to do this in modern C is this:

在现代C中执行此操作的正确方法是:

typedef struct {
    float alcohol;
    float price;
    char name[];
} drinks;

...

const char str NAME[] = "Cosmopolitan";
drinks* cosmo = malloc(sizeof(*cosmo) + sizeof(NAME));

cosmo->alcohol = 20.67f;
cosmo->price = 10.0f;
memcpy(cosmo->name, NAME, sizeof(NAME));
// (strcpy is fine too, but is slightly slower)

Please note that all the sizeof operator calls do take the null terminator in account, since these are C strings.

请注意,所有sizeof运算符调用都会使用null终结符,因为它们是C字符串。

#1


2  

you have a field name which is a char array of size 1 in your stucture.

你有一个字段名称,它是你的结构中大小为1的字符数组。

You performed a realloc(cosmo.name,length); which is undefined behaviour, which can explain that the numbers are then "ridiculous".

你执行了realloc(cosmo.name,length);这是未定义的行为,可以解释这些数字是“荒谬的”。

Your structure should either define a bigger size for the strings

您的结构应该为字符串定义更大的大小

struct drinks{
float alcohol;
float price;
char name[100];};

or define a pointer (set it to NULL so realloc works, or use malloc):

或定义一个指针(将其设置为NULL,以便realloc工作,或使用malloc):

struct drinks{
float alcohol;
float price;
char *name;};

And when you realloc/malloc, don't forget string terminator (+1) or use strdup

当你realloc / malloc时,不要忘记字符串终结符(+1)或使用strdup

cosmo.name = malloc(1+length);
strcpy(cosmo.name, name);

or

cosmo.name = strdup(name);

#2


2  

There are two problems: The first is that the structures name member is an array which will have a size fixed at the time of compilation. You can not reallocate that. Calling realloc will lead to undefined behavior.

有两个问题:第一个是结构名称成员是一个在编译时具有固定大小的数组。你无法重新分配。调用realloc将导致未定义的行为。

The next problem is that you then copy a to long string into the single-element array thereby writing out of bounds and again have undefined behavior.

接下来的问题是,然后将一个长字符串复制到单元素数组中,从而写出超出边界并再次具有未定义的行为。

The obvious and simple solution is to create the array with a larger size to begin with. You can also turn the name member into a pointer in which case you can allocate memory for it (with malloc or strdup). If you opt for the second solution and use malloc, remember that strings in C have a terminator. So a string like "hello" have six elements: The five you see and which are counted with strlen plus the terminator.

显而易见且简单的解决方案是创建具有更大尺寸的阵列。您还可以将名称成员转换为指针,在这种情况下,您可以为其分配内存(使用malloc或strdup)。如果您选择第二个解决方案并使用malloc,请记住C中的字符串有一个终止符。所以像“你好”这样的字符串有六个元素:你看到的五个元素和用strlen加上终结符计算的元素。

#3


1  

The correct way to do this in modern C is this:

在现代C中执行此操作的正确方法是:

typedef struct {
    float alcohol;
    float price;
    char name[];
} drinks;

...

const char str NAME[] = "Cosmopolitan";
drinks* cosmo = malloc(sizeof(*cosmo) + sizeof(NAME));

cosmo->alcohol = 20.67f;
cosmo->price = 10.0f;
memcpy(cosmo->name, NAME, sizeof(NAME));
// (strcpy is fine too, but is slightly slower)

Please note that all the sizeof operator calls do take the null terminator in account, since these are C strings.

请注意,所有sizeof运算符调用都会使用null终结符,因为它们是C字符串。