为什么使用char agrv而不是char ** argv作为main的参数导致以下输出?

时间:2015-06-20 13:47:56

标签: c++ c command-line-arguments main

当我这样做时:

$ prog_name 0
0

$ prog_name (from 0-7 characters)
48

$ prog_name 12345678
56

$ prog_name 1234567812345678
64

// and so on...

当我从命令行运行程序时,我得到了这个输入:

int main(int agrc, char argv[])

那么这些值来自何处以及它们为何增加8?

当我这样做时会发生什么:

Style.css

3 个答案:

答案 0 :(得分:5)

您的输出可能是"普通"的地址。 argv参数,即隐含转换解释 see comment below char。换句话说,我怀疑你拥有的东西相当于:

int main(int agrc, char **argv)
{
    printf("%d", (char) argv);
    return 0;
}

在我的机器上(CentOS 6 32位)反汇编的目标代码如下:

   0x080483c4 <+0>: push   %ebp
   0x080483c5 <+1>: mov    %esp,%ebp
   0x080483c7 <+3>: and    $0xfffffff0,%esp
   0x080483ca <+6>: sub    $0x10,%esp
   0x080483cd <+9>: mov    0xc(%ebp),%eax
   0x080483d0 <+12>:    movsbl %al,%eax
   0x080483d3 <+15>:    mov    %eax,0x4(%esp)
   0x080483d7 <+19>:    movl   $0x80484b4,(%esp)
   0x080483de <+26>:    call   0x80482f4 <printf@plt>

以及您发布的原始代码:

   0x080483c4 <+0>: push   %ebp
   0x080483c5 <+1>: mov    %esp,%ebp
   0x080483c7 <+3>: and    $0xfffffff0,%esp
   0x080483ca <+6>: sub    $0x20,%esp
   0x080483cd <+9>: mov    0xc(%ebp),%eax
   0x080483d0 <+12>:    mov    %al,0x1c(%esp)
   0x080483d4 <+16>:    movsbl 0x1c(%esp),%eax
   0x080483d9 <+21>:    mov    %eax,0x4(%esp)
   0x080483dd <+25>:    movl   $0x80484b4,(%esp)
   0x080483e4 <+32>:    call   0x80482f4 <printf@plt>

在这两种情况下,$0x80484b4"%d"格式说明符存储为字符串文字,0xc(%ebp)负责printf()使用的实际值:

(gdb) x/db 0xbffff324
0xbffff324: -60
(gdb) p $al
$3 = -60

请注意AL(一个字节累加器,即EAX的一部分)&#34;取出&#34;只有$ebp+0xc地址的第一个字节(我的CPU是小端,所以它实际上是LSB)。这意味着(char)转换确实&#34;截止&#34; argv地址。

因此,您可能会发现这些数字中的每一个都有log2(n)个未设置的最低有效位。这是由于指针类型对象的对齐要求。通常用于32位x86计算机alignof(char **) == 4

正如评论中已经指出的那样,你违反了C标准,所以它就是UB的一个例子。

答案 1 :(得分:-1)

根据C标准,关于main()

的签名
  

该实现声明此函数没有原型。

因此,如果传递不同类型的参数,编译器就不会出现问题。

在您的代码中,

int main(int agrc, char argv)

不是main()推荐的签名。它应该是

int main(int agrc, char* argv[])

或者,至少

int main(int agrc, char** argv)

否则,在托管环境中,行为未定义。您可以在C11标准,第5.1.2.2.1章中查看更多内容。

在您的情况下,如您所见,您将第二个参数设为char类型。根据标准规范,

  

如果argc的值大于零,则数组成员argv[0]argv[argc-1]包含指向字符串的指针,....

因此,在这里,提供的0作为指向 string 的指针传递给main(),该指针在char中被接受,而<html> <head> <title>Some title</title> <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> <script type='text/javascript'> $(document).ready(function(){ $('#searchdevice').blur(function(){ $('#explain').fadeTo(1000, 0); }); }); </script> </head> <body> <input type='text' name='input' id="searchdevice" class="search-field" placeholder="" autofocus/> <div id="explain">Search your device in the text field</div> </body> </html> 未定义行为。

答案 2 :(得分:-3)

堆栈上有一个字符串指针,但你在那里用char表示main,然后将其打印为小数。该字符串的内存地址是不可预测的,因此您会得到不可预测的输出。

试试这个:

int main( int argc, char* argv[] )
{
    printf( "%s", argv[1] );
    return 0;
}

我认为这会给你你的意图。