【问题标题】:Should I cast arrays to pointers when passing them to variadic functions like printf?在将数组传递给 printf 等可变参数函数时,我应该将数组转换为指针吗?
【发布时间】:2012-04-09 08:54:12
【问题描述】:

我可以直接将数组传递给 printf:

char text[1024] = "text";
printf("%s", text);

或者我应该将其显式转换为 char 指针:

char text[1024] = "text";
printf("%s", (char*) text);

我之所以这么问,是因为我认为它可能将数组元素直接复制到 va_list 中,而不是只放置一个指向第一个元素的指针。

【问题讨论】:

  • 只是不要忘记空终止符。
  • @sje397: "text" 是 {'t','e','x','t',0}
  • 是的 stefan,但如果您正在操作数组(并提出这个问题),请记住这一点。
  • @sje397 为什么需要记住零终结符?数组总是自动获取它,它是数组初始化的文本的一部分。此外,这个数组的创建方式,前四个之后的所有字符也被初始化为零。
  • 我并不是说它直接相关。我只是假设在数组中存储文本的人很可能会做一些事情,比如将文本从一个数组复制到另一个数组。此外,如果这样的人是一个相对初学者,正如这个问题向我建议的那样,那么他们可能想知道strlen 将返回一个小于您通常想要复制的字节数的数字。只是想提供帮助。

标签: c++ c printf


【解决方案1】:

是的,你可以直接传递一个数组。没错,数组名就是数组的地址,和char *没有区别。

【讨论】:

    【解决方案2】:

    (char*)texttext 在这个例子中几乎没有任何区别!当作为函数参数传递时,数组的基地址衰减为指针。

    事实上,即使text 不是char 数组,它仍然与printf 几乎没有任何区别,因为它是一个可变参数函数

    int printf(const char *format, ...);
    

    它只关心第一个参数。逻辑可能出错,但printf 不在乎!

    【讨论】:

      【解决方案3】:

      简短的回答,是的,C 中的数组 _are_a 指向它们的第一个元素的指针。 (编辑:更长的回答,实际上,C 中的数组是标识符或标签,它们只是名称,但在使用时作为不以 & 或 sizeof 开头的表达式的一部分,它们将被转换为指针或以其他方式计算为指针)。

      更长的回答:你看,函数不能真正接收数组作为参数,但编译器必须向它们发送一些东西,所以它会向它们发送一个指针。因此,第一句话可能应该以“就printf()之类的功能而言......”开头。

      有些函数声称采用数组,但这只是一种错觉。这两个功能是一样的。

      func(char *a);
      func(char a[]);
      

      下面的 C 常见问题解答条目更详细地介绍了数组和指针之间的细微差别:

      char a[] = "this";
      char *b = "that";
      

      a[0] 生成的代码与 b[0] 完全不同,但它们大致相同,因为下标运算符 [] 为我们提供了预期的结果。

      有趣的是,格式说明符“%s\n”也作为指针传递给printf()

      http://www.lysator.liu.se/c/c-faq/c-2.html

      Isn't an array/arrayname always a pointer to the first element in C?

      【讨论】:

      • 第一句话是对的。第二个不是。 C中的数组是数组。 C中的指针是指针。数组不是指针(否则,不会有自动转换,正如您自己在第一句话中提到的)
      • 其实第一句话是正确的。数组是 not 指针。它们在许多情况下(不是全部)衰减为指针,但只是尝试增加一个数组和一个指针 - 后者有效,前者无效:char x[10]; char *y = x; x++; y++; 不适用于 x++
      • 更接近“机器”,数组只不过是位于某处的数据。访问内存中的元素数组(这些数据)的“明显”方法是通过指针。但远离机器 PoV,给定 T a[N]a 必须是指向第一个元素的不可变 reference(指针);或许可以简单地说,它不可能是一个lvalue,和&(a[0])完全一样,这就证明了a++的失败。所以我想说,a 只是&(a[0]) 的语法糖,所以说a 只是指向数组第一个元素的指针是正确的。
      • 编辑使用不那么模棱两可的语言,同时尽量不抄袭。在 c 常见问题解答中找到了我正在寻找的参考。
      【解决方案4】:

      除非它是sizeof 或一元& 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则表达式 类型为“N- “T”的元素数组将被替换为“指向T”类型的表达式,其值是数组第一个元素的地址。

      当你写作时

      printf("%s", text);
      

      表达式text 被替换为char * 类型的新表达式,其值为&text[0],这个指针值就是传递给printf 的值。这意味着您不必强制转换参数。这也意味着您不能将数组表达式作为函数参数传递并让被调用函数将其作为数组type 接收。转换发生在调用函数之前。

      【讨论】:

        【解决方案5】:

        指针和数组的名称是可交换的。 (除了内存分配)

        当你有

        char *a = "abcdef";
        char b[5];
        

        你可以写

        char z = a[2]; // 'c'
        char x = *b;
        char y = *(b+2);
        

        但你做不到

        b ++; 
        

        您可以将array b 视为char * const b 为不可修改的指针

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-24
          • 2013-02-15
          • 1970-01-01
          • 1970-01-01
          • 2012-11-23
          • 1970-01-01
          相关资源
          最近更新 更多