特殊字符长度

Special character length

今天发现了一件很奇怪的事

在上面的代码中,我看到 utrlen(&eot) (utrlen == strlen) 等于二,而 utrlen(&etx) == 1.

最好的部分:当我用 etx 交换声明顺序时,utrlen(&eot) == 1utrlen(&etx) == 2...

char            **get_ukey_string()
{
  static char   eot = 0x4;
  static char   etx = 0x3;
  static char   *ukey_string[NB_UKEY] = {
    "\b", "\r", "[B", "[=10=]", "\n", "[D", "[C", "[A", &etx, &eot
  };

  return (ukey_string);
}

t_hashtable     *new_ukey_htable(int fd)
{
  char          **ukey_string;
  t_hashtable   *htable;
  t_hashnode    *hnode;
  char          *key;
  unsigned int  i;
  size_t        size;

  if ((htable = new_hashtable(NB_UKEY)) == NULL)
    return (NULL);
  ukey_string = get_ukey_string();
  i = 2;
  while (i < NB_UKEY + 2)
    {
      key = ukey_string[i - 2];
      size = utrlen(key);
      if (((hnode = new_hashnode(sutrdup(key, size), size, i)) == NULL)
          || htable->add_node(htable, hnode))
        {
          delete_hashtable(htable);
          return (NULL);
        }
      ++i;
    }
  return (htable);
}

有人知道为什么吗?

eot 和 etx 是 char,而不是 char *,因此您不能对它们应用 strlen,因为它们没有空终止符。

strlen 函数(为什么称它为 utrlen?)接受类型为 const char* 的参数。该参数必须指向 字符串 的初始字符,定义为 "a contiguous sequence of characters terminated by and including the first null character".

使用已声明的 char 对象的地址调用 strlen 是合法的;地址类型 char*(指向 char 的指针)与要传递给 strlen 的所需类型匹配。但它不是 字符串 的初始字符,因此行为未定义。

实际上,strlen 将从您为其提供地址的 char 对象开始,并迭代直到它看到空字符 '[=20=]'.

如果 char 对象恰好具有值 '[=20=]',它会立即找到它并且 returns 0 -- 这不是特别有用。

如果它有其他值,strlen 将尝试扫描内存中不属于对象的字节。结果是未定义的行为。

不要那样做。