C中的结构问题

时间:2009-08-12 09:18:56

标签: c

我的结构如下:

typedef struct {
      unsigned long attr;
      char fileName[128];
} entity;

然后我尝试分配一些值,但收到错误消息......

int attribute = 100;
char* fileNameDir = "blabla....etc";

entity* aEntity;

aEntity->attr = attributes;
aEntity->fileName = fileNameDir;

编译告诉我:

  

错误:#137:表达式必须是可修改的左值           aEntity-> fileName = fileNameDir;

为什么我不能在这里将这个角色分配给结构中的角色?

由于

12 个答案:

答案 0 :(得分:11)

您无法指定指向数组的指针。使用strncpy()复制字符串:

strncpy( aEntity->fileName, fileNameDir, 128 );

如果源长度超过128,这将使目标不为空终止。我认为最好的解决方案是拥有一个更大的缓冲区,只复制N个字节并将第N + 1个字节设置为零:

#define BufferLength 128

typedef struct {
  unsigned long attr;
  char fileName[BufferLength + 1];
} entity;

strncpy( aEntity->FileName, fileNameDir, BufferLength );
*( aEntity->FileName + BufferLength ) = 0;

答案 1 :(得分:11)

  • 您正在将char[](以及char*,FTM)视为字符串。哪个不是。您无法分配数组,您必须复制值。此外,文件名的长度128似乎是任意的,可能是缓冲区溢出的潜在来源。使用std::string有什么问题?这可以摆脱所有这些问题。
  • 您正在定义指向某些entity的指针,不对其进行初始化,然后使用它,就好像它指向的随机地址是有效的entity对象一样。
  • C ++中不需要typedef struct,因为与C不同,C ++ struct名称与其他名称存在于同一名称空间中。

如果你绝对必须使用问题中定义的struct(它是预定义的),那么请查看其他答案并自己"The C Programming Language" 。否则,您可能想要使用此代码:

struct entity {
  unsigned long attr;
  std::string fileName;
};

entity aEntity;
aEntity.attr = 100;
aEntity.filename = "blabla....etc";

答案 2 :(得分:5)

您应该复制文件名字符串,而不是更改它指向的位置。

答案 3 :(得分:5)

你在写C或C ++吗?没有一种称为C / C ++的语言,根据您使用的语言,您的问题的答案会有所不同。如果您使用的是C ++,则应使用std::string而不是普通的旧C字符串。

您的代码中存在一个主要问题,我没有看到其他海报地址:

entity* aEntity;

声明aEntity(应为anEntity)作为指向entity的指针,但未初始化。因此,像所有未初始化的指针一样,它指向垃圾。因此:

aEntity->attr = attributes;

调用未定义的行为。

现在,如果正确初始化anEntityanEntity->fileName是一个数组,而不是指向字符数组的指针(请参阅C FAQ列表中的question 6.2)。因此,您需要将fileNameDir指向的字符串复制到为anEntity->fileName保留的内存块。

我看到很多使用strncpy的建议。我不支持将strncpy视为strcpy的更安全的替代品,因为事实并非如此。另请参阅Why is strncpy insecure?

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

typedef struct st_entity {
    unsigned long attr;
    char fileName[FILENAME_MAX + 1];
} entity;

int main(void) {
    int status = EXIT_FAILURE;
    unsigned long attribute = 100;
    char *fileNameDir = "blabla....etc";

    entity *anEntity = malloc(sizeof(*anEntity));

    if ( anEntity ) {
        anEntity->attr = attribute;
        anEntity->fileName[0] = '\0';
        strncat(anEntity->fileName, fileNameDir, sizeof(anEntity->fileName) - 1);
        printf("%lu\n%s\n", anEntity->attr, anEntity->fileName);
        status = EXIT_SUCCESS;
    }
    else {
        fputs("Memory allocation failed", stderr);
    }

    return status;
}

请参阅strncat

答案 4 :(得分:1)

你正在尝试使用char *,就好像它是一个字符串,它不是。特别是,您告诉编译器将filename(128个大小的char数组)设置为fileNameDir指向的内存地址。

使用strcpy:http://cplusplus.com/reference/clibrary/cstring/strcpy/

答案 5 :(得分:1)

你不能将一个指向char的指针分配给一个char数组,它们不兼容,你需要将内容从一个复制到另一个,strcpy,strncpy ......

答案 6 :(得分:1)

使用strncpy():

strncpy( aEntity->fileName, fileNameDir, sizeof(entity.fileName) );
aEntity.fileName[ sizeof(entity.fileName) - 1 ] = 0;
  

strncpy()函数类似,   除了不超过n个字节   src被复制。因此,如果没有   。的前n个字节中的空字节   src,结果不会   以null结尾。 See man page.

答案 7 :(得分:1)

1)行char* fileNameDir = "blabla....etc"创建一个指向char的指针,并为指针指定一个地址;在这种情况下,地址是驻留在内存中的文本"blabla....etc"的地址。

2)此外,根本不能分配数组(char fileName[128]);您只能分配给数组的成员(例如array[0] = blah)。

知道上面的(1)和(2),显然为数组分配地址不是一件有效的事情,原因有多种。

必须做的事情是将fileNameDir指向的数据复制到数组(即数组成员),例如使用strncpy

另请注意,您只是分配了一个指向结构的指针,但没有内存来保存结构数据本身!

答案 8 :(得分:1)

首先,这应该是C还是C ++?两者不一样或可以自由互换,每个人的“正确”答案都不同。

如果这是C,那么请注意不能使用'='运算符将字符串分配给数组;你必须使用strcpy()或strncpy():

/**
 * In your snippet above, you're just declaring a pointer to entity but not
 * allocating it; is that just an oversight?
 */
entity *aEntity = malloc(sizeof *aEntity); 
...
strcpy(aEntity->fileName, fileNameDir);

strncpy(aEntity->fileName, fileNameDir, sizeof aEntity->fileName);

适当检查终止空字符。

如果这是C ++,则应该使用std :: string类型而不是char *或char []。这样,你可以使用'='运算符

分配字符串数据
struct entity {unsigned long attr; std::string fileName};

entity *aEntity = new entity;
std::string fileNameDir = "...";
...
entity->fileName = fileNameDir;

答案 9 :(得分:1)

主要问题是你声明了一个指向结构的指针,但没有为它分配空间(除非你遗漏了一些关键代码)。以及其他人注意到的其他问题。

答案 10 :(得分:0)

问题在于,您不能仅使用指针而不将其初始化为同一数据类型的变量,而该数据类型中的变量是实体变量。如果没有这个,指针将指向一些包含一些垃圾值的随机存储器位置。尝试使用此类指针时,您会遇到分段错误。

要注意的第二件事是你不能使用赋值运算符(=)直接将字符串赋值给变量。您必须使用string.h头文件中的strcpy()函数。

代码的输出是:  100 blabla ......等等。

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


typedef struct
{
      unsigned long attr;
      char fileName[128];
} entity;

void main()
{
        unsigned long int attribute = 100;
        char *fileNameDir = "blabla....etc";

        entity struct_entity;
        entity *aEntity = &struct_entity;

        aEntity->attr = attribute;
        strcpy(aEntity->fileName, fileNameDir);

        printf("%ld %s", struct_entity.attr, struct_entity.fileName);
}

答案 11 :(得分:-1)

对于char fileName [128],fileName是128个字符长的数组。你可以改变fileName。 您可以使用strncpy(aEntity-&gt; fileName,fileNameDir,128)更改文件名指向的内存内容;