puts()函数和printf函数的区别
puts()函数只用来输出字符串,没有格式控制,里面的参数可以直接是字符串或者是存放字符串的字符数组名。
printf()函数的输出格式很多,可以根据不同格式加转义字符,达到格式化输出。
puts()函数的作用与语句printf("%s\n",s);的作用形同。
 
例子:
#include  <stdio.h> 
   
  int  main(  void  ) 
  { 
        puts(  "Hello  world  from  puts!"  );   //字符串,最后隐含带有'\0'字符
  } 
  Output 
  Hello  world  from  puts! 
main()
{
    static char a[] = {'H','I','!','!'};
    puts(a);
}
则输出 Hi!!烫烫烫烫烫烫烫烫烫烫烫烫 (后面都是乱码)
原因: a在结尾处缺少一个空字符('\0'), 所以它不是一个串,这样, puts() 就不知道什么时候停止输出, 它将会把 a 后面内存单元中的内容都打印出, 直到它在什么地方碰到了一个空字符为止。
//==============
cat hello.c
#include <stdio.h>
int main(void)
{
printf("hello world!\n");
}
//========================
gcc -S hello.c -o hello.s 生成汇编代码
//========================
cat hello.s
//=========================
.file "hello.c"
.section .rodata
.LC0:
.string "hello world!"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
movl $.LC0, (%esp)
call puts //========这里不是printf
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)" //=======gcc版本
.section .note.GNU-stack,"",@progbits
 
修改printf()的参数后
//==========================
#include <stdio.h>
int main(void)
{
printf("hello world! addr=0x%08x\n",printf);
}
//==========================
gcc -S hello.c
//======================
cat hello.s
//===========.file "hello.c"
.section .rodata
.LC0:
.string "hello world! addr=0x%08x\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
函数printf作用subl $20, %esp
movl $printf, 4(%esp)
movl $.LC0, (%esp)
call printf //=================编译后的汇编代码已经是printf了
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)"
.section .note.GNU-stack,"",@progbits
原因:puts()函数的作用与语句printf("%s\n",s);的作用形同。gcc可能对其进行了优化。