繁体   English   中英

分配char * []结构数据元素会发出警告

[英]Assigning char*[] struct data element gives warning

我有一个结构,其中包含char * []类型的值。 它的定义如下:

struct background_element
{
    pid_t pid;
    int number;
    char *full_command[MAX_ARGS];
};

我也有一个全局char * []变量args。

char *args[MAX_ARGS];

我尝试创建一个类型为struct background_element的新变量,并分配full_command值,如下所示:

struct background_element bg_elem = { .pid = child, .number = num_background, .full_command = args};

但是,将args分配给.full_command似乎会引发以下警告:“警告:从不兼容的指针类型进行初始化。”

我尝试使用strcpy,但是由于它们不是char []而是char * [],所以似乎不起作用。 我有点不知道如何分配它。 任何帮助,将不胜感激。

如@ user3386109所说,这是因为无法将char *full[MAX_ARGS]分配给它。 根据您的情况,从此处有两条路径。 如果不打算通过其他代码或通过释放其字符串元素来修改args,那么我们可以像这样将full_command的元素指向它们:

struct background_element bg_elem = {.pid = child, .number = num_background};
for (unsigned int i = 0; i < MAX_ARGS; i++) {
    bg_elem.full_command[i] = args[i];
}

但是,如果您需要复制字符串,则必须使用malloc为字符串创建空间,然后使用strcpy复制数据:

for (unsigned int i = 0; i < MAX_ARGS; i++) {
    int str_len = strlen(args[i]);
    bg_elem.full_command[i] = malloc((str_len + 1) * sizeof(char));
    strcpy(bg_elem.full_command[i], args[i]);
}

上面的for循环优先:

  1. 获取第i个参数的长度
  2. 将足够的内存分配给bg_elem.full_command的第i个指针
    • 我们需要str_len + 1因为我们需要为空字符提供空间
  3. 将字符串从args复制到bg_elem.full_command

最后,如果您需要从args复制字符串,请不要忘记遍历并在结束时释放该内存。

for (unsigned int i = 0; i < MAX_ARGS; i++) {
    free(bg_elem.full_command[i]);
}

注意:如果需要将要复制的内存清零,则calloc会更好。 但是,由于我们使用的是strcpy,因此malloc可以正常工作。

C语言中的数组对象仅限于两种初始化器:

  1. {}封闭的初始值设定项,即一对{}其中各个初始项用于内部数组元素
  2. char []数组的字符串文字。

您的初始值设定项不属于这些类别。 无效。 您不能通过另一个数组初始化一个数组(除了上面的情况2)。

形式上,您可以明确地将其拼写出来

struct background_element bg_elem = 
{ 
  .pid = child, 
  .number = num_background, 
  .full_command = { args[0], args[1], /* ... and so on */ }
};

但这并不是真正可行的方法。 一个更好的主意是

struct background_element bg_elem = 
{ 
  .pid = child, 
  .number = num_background
};

static_assert(sizeof bg_elem.full_command == sizeof args, "");
memcpy(bg_elem.full_command, args, sizeof args);

尽管它可能会因“双重初始化”问题而受到影响。

PS您要尝试做的事情称为初始化 ,而不是赋值 在C中,赋值是完全不同的事情。

char *args[MAX_ARGS];

args是MAX_ARGS指针的数组。 args本身指向第一个指针的内存。 args保存第一个指针所在的内存地址。 args[0]是第一个指针的值。 args[0][0]意思是,我们转到第一个指针的内存,然后转到该指针指向的内存地址,然后获取该内存地址中第一个字节的值。

char *full_command[MAX_ARGS];

现在,这也是MAX_ARGS指针的数组。 full_command指向MAX_ARGS * sizeof(char*)个字节长度的内存区域。 full_command[0]是该内存区域内第一个指针的值。
现在让我们尝试分配:

full_command = args;

现在,我们在args中获取第一个指针的内存地址的值,并将该值分配给full_command变量。 full_command的内存已丢失,其他任何句柄都无法再访问它。 现在args[0] = smth仅且仅当full_command[0] = smth full_command指向args指向的内存区域。
要复制数组VALUES,您需要复制数组的每个VALUE:

for (size_t i = 0; i < MAX_ARGS; ++i) { 
     full_command[i] = args[i];
}

或使用memcpy:

memcpy(full_command, args, sizeof(full_command));

在执行此操作后, full_command指向args的不同区域,两者均为sizeof(char*) * MAX_ARGS字节长。 它们都具有相同的值。
您需要分配每个数组值:

struct background_element bg_elem = {
   .pid = child, 
   .number = num_background, 
   .full_command = { args[0], args[1], args[2], ....<up until MAX_ARGS> }, 
};

这不是很有用,每次MAX_ARGS更改时都需要修改。 因此,请使用memcpy或循环:

struct background_element bg_elem = {
    .pid = child, 
    .number = num_background, 
};
memcpy(bg_elem.full_command, args, sizeof(bg_elem.full_command));

您在上面有很多正确答案。 简而言之:数组在C语言中很奇怪。您可以初始化它们,但不能分配它们。 您不能在结构初始化程序中单独对其进行初始化,但是可以将它们作为结构分配的一部分进行分配。

#include <string.h>

int main(int argc, char *argv[])
{
  char *test1 [3] = {"a", "b", "c"}; //initialization, not assignment; allowed
  char *test2 [3];

  //test2 = test1; //assignment of arrays; not allowed

  memcpy(test2, test1, sizeof(test1)); //the right way to do a shallow array copy
}

但也令人困惑:

#include <string.h>

struct _array_holder
{
  char *array[3];
};

int main(int argc, char *argv[])
{
  struct _array_holder test1 = {{"a", "b", "c"}}; //_struct_ initialization; allowed
  struct _array_holder test2;

  test2 = test1; //assignment of _structs_; allowed!

  memcpy(&test2, &test1, sizeof(test1)); //also a fine way to copy a struct
}

因此,不幸的是,没有漂亮的方法(即优雅的语法)来做您想要的事情。 这至少是一种合理的独立式方法,可以利用结构中的数组分配起作用的事实,从而避免您每次要填充新结构时都必须写几行初始化:

#include <string.h>
#include <unistd.h>

#define MAX_ARGS 5
struct background_element
{
  pid_t pid;
  int number;
  char *full_command[MAX_ARGS];
};

//something akin to a constructor for the struct
struct background_element init_background_element(pid_t pid, int number, char *full_command[])
{
  struct background_element ret = {.pid = pid, .number=number};
  memcpy(ret.full_command, full_command, sizeof(ret.full_command));
  return ret;
}

int main(int argc, char *argv[])
{
  pid_t child = 1;
  int num_background = 5;
  char *args[MAX_ARGS] = {"a", "b"};

  //use of the constructor-like thing
  struct background_element bg_elem = init_background_element(child, num_background, args);

  return bg_elem.pid;
}

暂无
暂无

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

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