【问题标题】:Using (+ve integer) + "some string " in printf? [duplicate]在 printf 中使用 (+ve integer) + "some string"? [复制]
【发布时间】:2017-12-21 14:05:27
【问题描述】:
#include <stdio.h>

void main() {
    printf(2 + "abcdefgh");
}

这段代码如何打印cdefgh?如果我使用 2- 或 2* 或任何其他运算符,编译器会抛出错误。

【问题讨论】:

  • 如果您知道2 + any_pointer 等于any_pointer + 2 可能更有意义,这等于&amp;any_pointer[2]。
  • "The format string is a character string, beginning and ending in its initial shift state"
  • 你对2 * "abcdefgh" 有什么期待?

标签: c arrays printf pointer-arithmetic


【解决方案1】:

在这段代码中

printf(2 + "abcdefgh");

与

相同
printf(&("abcdefgh"[2]));

其中,参数用作printf() 中的格式字符串。

详细说明,从 字符串文字 的属性,引用 C11,第 §6.4.5/P6 章

在翻译阶段 7,一个字节或零值代码被附加到每个多字节 由一个或多个字符串文字产生的字符序列。78) 多字节字符 然后使用序列来初始化静态存储持续时间和长度的数组 足以包含序列。对于字符串文字,数组元素有 键入char,并使用多字节字符的各个字节进行初始化 顺序。 [...]

对于数组,来自第 §6.3.2.1 章,

除非它是sizeof 运算符、_Alignof 运算符或 一元 &amp; 运算符,或者是用于初始化数组的字符串文字,该表达式具有 type ‘‘array of type’’ 被转换为类型为 ‘‘pointer to type’’ 的表达式,它指向 到数组对象的初始元素并且不是左值。 [...]

所以,在函数调用参数的情况下,作为加法运算符的参数之一,字符串字面量实际上是字面量中第一个元素的地址,然后是加法,即 指针算术,发生。结果是指向第三个元素的递增指针(C 数组是从 0 开始的索引)。

也就是说,正如上一段所强调的,指针运算仅对 加法 操作有效,对乘法操作无效。

【讨论】:

    【解决方案2】:

    当使用诸如"abcdefgh" 之类的字符串文字时,您实际上有一个指向该字符串所在的内存部分的指针。基本上,您将一个指向该位置的指针传递给printf,并指示它将指针向前移动 2 个位置,从而导致从第三个字符而不是第一个字符开始的字符串

    请注意,您可以使用-,但您需要像使用指针算术一样使用它,例如

    printf("abcdefgh" - 0); // using -N where N &gt;0 would be UB

    所以,这段代码是有效的

    int main()
    {
        printf("abc\n" - 0);
        printf(1+"def");
        return 0;
    }
    

    但使用*,/ 不会(同样位运算符|,&amp; 也无效)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2019-12-06
      • 1970-01-01
      • 2011-07-10
      相关资源
      最近更新 更多