简体   繁体   English

char *在结构中,指向char数组,然后使用strncpy。 尝试避免动态分配内存

[英]char * in a struct, pointing to a char array, then using strncpy. Trying to avoid dynamically allocated memory

struct person
{
    char age [3];
    char * name;
};

char nameBuf[20];

person Natasha;
person * p_person;
p_person = &Natasha;

Natasha.name = nameBuf;

createPerson (person * resultingPerson, int p_age, const char * p_name)
{

    sprintf(resultingPerson->age, "%03d", p_age);

    strncpy(resultingPerson->name, p_name, strlen(p_name));
}


createPerson (p_person, 29, "Chelsea");

This code fails at the strncpy call. 此代码在strncpy调用时失败。 I can't use dynamically allocated memory. 我不能使用动态分配的内存。 What is the best way to handle this? 处理此问题的最佳方法是什么? Why doesn't this work once the name* is pointing to nameBuf[20] a char array and then using strncpy? 一旦name *指向nameBuf [20]一个char数组,然后使用strncpy,为什么这不起作用?

Thank you 谢谢

First off, age is only 3 and you are trying to write 4 bytes 3 digits and a null. 首先,年龄只有3岁,您正在尝试写入4个字节的3位数字和空值。 Also, normally your length parameter to strncpy is the size of the destination minus 1 so that you have room to add null (if the source string is shorter, strncpy will add the null). 同样,通常,您给strncpy的length参数是目标的大小减去1,以便您有空间添加null(如果源字符串较短,则strncpy将添加null)。

#define NAMEBUFSIZ 20
char namebuf[NAMEBUFSIZ];
typedef struct person
{
    char age [3];
    char *name;
} person;

person Natasha;
person * p_person;
p_person = &Natasha;
p_person->name = namebuf;

createPerson (person * resultingPerson, int p_age, const char * p_name)
{
    char tmpbuf[5];

    snprintf(tmpbuf, sizeof(tmpbuf), "%03d", p_age);
    memcpy(resultingPerson->age, tmpbuf, sizeof(resultingPerson->age));
    resultingPerson->name[NAMEBUFSIZ-1] = '\0';
    strncpy(resultingPerson->name, p_name, NAMEBUFSIZ-1);
}
createPerson (p_person, 29, "Chelsea");

It's still not clean, though. 不过,它仍然不干净。 Can you guarantee the age will be reasonable, and that only short names (19 or fewer characters) are passed? 您可以保证年龄合理吗,并且只传递短名称(不超过19个字符)?

NOTE: changed sprintf to snprintf as the comment below is correct, sprintf is quite unsafe as your code example demonstrates 注意:由于以下注释正确,因此将sprintf更改为snprintf,如代码示例所示,sprintf相当不安全

@chqrlie - you helped my track down my problem. @chqrlie-您帮助我找到了我的问题。 My problem was that I didn't want a string, only a char array. 我的问题是我不想要一个字符串,只想要一个char数组。 When I was using sprintf it was clobbering my char * name that I had originally pointed to nameBuf[] by writing the final null char, which I was not expecting. 当我使用sprintf时,它通过写入最终的空字符来破坏我最初指向nameBuf []的char *名称,这是我没有想到的。 I put it through a debugger and watched the address to the buffer change. 我将其放入调试器,并查看缓冲区更改的地址。 I didn't know why that was happening until I read your comment. 在阅读您的评论之前,我不知道为什么会这样。

I ended up writing my own itoa, without a null char, then ended by using memcpy(). 我最终编写了自己的itoa,没有空字符,然后使用memcpy()结束了。

Thank you for your help! 谢谢您的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM