使用char **的项目(在声明后初始化之后)

时间:2012-06-28 00:09:43

标签: c arrays initialization pipe

正如 caf https://stackoverflow.com/a/1113041/1354779中谈到的那样, 当声明变量初始化已声明的数组时,有一种方法可以使用初始化器。 这很好,我现在想知道是否有办法逐个使用数组中的每个项目。

我用它来通过管道传递一个命令列表,我知道这个有效:

char* script[]={"report blabla","report bla"};
char line[200];
char** command;
for (command = script ; **command ; **command ? command++ : 0){
    if (**command){
        SendCommand(*command, line, sizeof(line));
    }   
}

但是当我尝试下面的代码时,我在pipe_GWB9.exe中的0x778915de处出现“未处理的异常:0xC0000005:访问冲突读取位置0xcccccccc”:

char* request[] = {"report watact"};
char line[200];
// [...] Other code [...]
static const char *tmp[8] = 
  {
  "report molality H+",
  "report molality Cl-",
  "report molality Ca++",
  "report molality Mg++",
  "report molality K+",
  "report molality Fe++",
  "report molality SO4--",
  "report molality Na+"
  }; 
  memcpy(request, tmp, sizeof request);
char** command;
command=request;
SendCommand(*command, line, sizeof(line));
// Until here, everything works great.
**command ? command++ : 0;
SendCommand(*command, line, sizeof(line));
// But THAT doesn't work!!

您是否可以帮我调用数组请求中的其他项?

谢谢

1 个答案:

答案 0 :(得分:1)

char* request[] = {"report watact"};

request是一个指向char的指针数组,包含1个元素。

static const char *tmp[8] = 
  {
  "report molality H+",
  "report molality Cl-",
  "report molality Ca++",
  "report molality Mg++",
  "report molality K+",
  "report molality Fe++",
  "report molality SO4--",
  "report molality Na+"
  }; 

tmp是一个指向char的指针数组,包含8个元素。

memcpy(request, tmp, sizeof request);

您将sizeof request == 4中的前四个字节(假设tmp)复制到request,即将tmp的第一个元素复制到{{1}的第一个元素中1}}。

request

足够简单; char** command; command=request; 现在指向command的第一个(也是唯一的!)元素。

request

糟糕。您刚刚超出**command ? command++ : 0; command)的范围,因为request只包含一个元素。然后在下一行调用request时取消引用它,这会给你seg错误。请注意,这里可能发生任何事情,因为您正在调用UB。

例如,如果切断两个数组之间的代码,可能会发生的事情是字符串SendCommand被发送两次因为将指针递增超过{{1}的范围很可能只是把你带到开头"report molality H+"

如果要将request复制到tmp,则需要确保两个数组的大小相同(或至少tmprequest一样大request)。

顺便说一下,这个三元表达式有点傻:

tmp

你只关心一个分支,为什么要使用三元组呢?喜欢:

**command ? command++ : 0;

也就是说,这不是一种检查数组边界的安全方法(正如您所发现的那样)。您正在将指针数组视为指向char的指针,即扫描直到找到NULL终止符。

数组没有NULL终止符,你只是走过它的边界并调用未定义的行为,所以你需要分别跟踪大小并检查它。