【问题标题】:Syntax of printf in CC中printf的语法
【发布时间】:2021-09-16 00:46:03
【问题描述】:

我是C初学者,主要使用以下两种格式的printf

#include <stdio.h>

//Compiler version gcc  6.3.0

int main()
{
  int c=5;
  printf("Hello, World!\n");
  printf("%d",c);
  return 0;
}

但是最近发现printf还有另外一种写法,即printf(string pointer),这个格式怎么和其他两个这么不同,没有引号,为什么有string ,这个问题可能很愚蠢,但请尝试理解我只是一个初学者。

【问题讨论】:

  • 其实和你用printf("Hello, World!\n")完全一样。另请注意,这并不是 printf 函数的真正不同形式,只是在某些情况下你传递了额外的参数,而对一些你没有。
  • 另请注意(这非常重要):您应该永远将变量作为格式字符串传递。如果您将printf 与用户输入一起使用,会阻止用户在输入中提供格式说明符,从而导致print 尝试使用实际上不存在的参数。如果要打印用户输入的字符串,请使用printf("%s\n", user_input_string) 或puts(user_input_string)。
  • printf 只有一个定义:int printf(const char *restrict format, ...);。只需阅读the documentation
  • 请注意printf 是variadic function。

标签: c printf implicit-conversion string-literals


【解决方案1】:

虽然它在您的编辑器中看起来不同,但实际上是相同的。

当你写作时

printf("Hello, World!\n");

在您的编辑器中,您的编译器原则上将其更改为

char* hidden_unnamed_string = "Hello, World!\n";
printf(hidden_unnamed_string);

字符串“Hello, World!\n”被称为字符串文字。编译器将(自动)将它放在内存中的某个位置,然后使用该内存地址调用printf。

这是一个来自 godbolt.org 的例子

在左侧是 C 程序,就像它在编辑器中的样子。右边是编译好的程序。

注意字符串是如何位于代码块之外并用 LC0 标记的。然后在调用打印函数之前将代码块 LC0 加载到 edi 中(即字符串的地址/指针加载到 edi 中)。

还要注意编译器决定使用puts 而不是printf。进一步注意,字符串的存储没有\n。原因是puts不像printf会自动添加一个\n。

【讨论】:

    【解决方案2】:

    对于初学者而不是这个 printf 调用

    printf("Hello, World!\n");
    

    你可以使用 puts like 的调用

    puts( "Hello, World!" );
    

    字符串文字"Hello, World!\n"在内部表示为一个字符数组,如

    char string_literal[] = 
    { 
        'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\n', '\0' 
    };
    

    表达式中使用的数组被隐式转换(极少数例外)为指向其第一个元素的指针。

    所以在这次通话中

    printf("Hello, World!\n");
    

    用作函数调用参数的字符数组被转换为类型为char * 的指针,指向其第一个元素'H'。你可以想象如下方式

    printf( &"Hello, World!\n"[0] );
    

    因此,该函数处理char * 类型的指针。你可以通过引入一个中间变量来做同样的事情

    char *s = "Hello, World!\n";
    printf( s );
    

    或

    char *s = "Hello, World!\n";
    printf( "%s", s );
    

    或

    char *s = "Hello, World!";
    printf( "%s\n", s );
    

    或

    char *s = "Hello, World!";
    puts( s );
    

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 1970-01-01
      • 2023-04-09
      • 2022-12-21
      • 2015-02-28
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多