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

时间:2018-08-21 23:20:19

标签: c arrays struct

我有一个结构,其中包含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 * [],所以似乎不起作用。我有点不知道如何分配它。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:2)

正如@ user3386109所说,这是因为无法分配const express = require('express') const proxy = require('express-http-proxy'); const http = require('http') const app = express(); app.use('/admintool', proxy('localhost:2000')); http.createServer(app).listen(8080, () => console.log('proxy server listening on port 8080!')); 。根据您的情况,从此处有两条路径。如果不打算通过其他代码或通过释放其字符串元素来修改args,那么我们可以像这样将full_command的元素指向它们:

char *full[MAX_ARGS]

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

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];
}

上述for循环优先:

  1. 获取第i个参数的长度
  2. 为bg_elem.full_command的第i个指针分配足够的内存
    • 我们需要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]); } ,因为我们需要空格来容纳空字符
  3. 将字符串从args复制到bg_elem.full_command

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

str_len + 1

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

答案 1 :(得分:1)

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);

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

P.S。您尝试执行的操作称为初始化,而不是赋值。在C中分配是完全不同的事情。

答案 2 :(得分:0)

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));

答案 3 :(得分:0)

您在上面有很多正确答案。简而言之:数组在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;
}