0

正如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!!

您能帮我调用数组请求的其他项目吗?

谢谢

4

1 回答 1

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+"
  }; 

tmpchar是一个包含 8 个元素的指针数组。

memcpy(request, tmp, sizeof request);

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

char** command;
command=request;

很简单;command现在指向 . 的第一个(也是唯一一个!)元素request

**command ? command++ : 0;

哎呀。您刚刚越过了command( request) 的边界,因为request只包含一个元素。然后在调用下一行时取消引用它SendCommand,这会给您带来段错误。请注意,这里可能发生任何事情,因为您正在调用 UB。

例如,如果你剪掉两个数组之间的代码,可能会"report molality H+"发生字符串被发送两次,因为将指针递增到 的边界之外request很可能只会让你跳到开头tmp

如果要将所有内容复制tmp到其中,request则需要确保两个数组的大小相同(或至少与request一样大tmp)。

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

**command ? command++ : 0;

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

if(**command)
    command++;

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

数组没有 NULL 终止符,您最终只是越过它的边界并调用未定义的行为,因此您需要单独跟踪大小并对其进行检查。

于 2012-06-28T00:17:45.773 回答