Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果argv不是char类型,C怎么办**_C_Command Line_Arguments - Fatal编程技术网

如果argv不是char类型,C怎么办**

如果argv不是char类型,C怎么办**,c,command-line,arguments,C,Command Line,Arguments,我在C中胡闹,决定尝试将argv的类型从char*改为int,看看会发生什么。我写道: #include <stdlib.h> #include <stdio.h> int main(int argc, int argv ) { printf("arg is %d \n", argv); } (该程序称为dink)。发生什么事了?C在编译时做什么?如果我使用的数据类型不是int,比如double、结构或其他什么,会发生什么情况?argv作为指向字符串指

我在C中胡闹,决定尝试将argv的类型从char*改为int,看看会发生什么。我写道:

#include <stdlib.h>
#include <stdio.h>
int main(int argc, int  argv )
{
        printf("arg is %d \n", argv);
}

(该程序称为dink)。发生什么事了?C在编译时做什么?如果我使用的数据类型不是int,比如double、结构或其他什么,会发生什么情况?

argv
作为指向字符串指针数组的指针传递给您的程序

如果你告诉编译器它是一个
int
,指针的字节将被解释为
int
,你将得到一个内存地址。(在64位系统上,可能会发生崩溃)

如果您假装它是一个
浮点值
,编译器可能会将这些字节/位解释为IEE-754编码的浮点值,从而产生一个不同的奇怪数字。(具体发生什么取决于调用约定)

如果您假装它是与指针宽度不同的任何类型,则可能会崩溃

这个故事的寓意是 C完全按照你说的去做。由你来告诉它如何解释事物。

好吧

Argv是一个数组。在C语言中,数组只是指针。指针在内部只是内存位置的整数。因此,您看到的数字是内存中的位置。(我猜否定是因为它不是无符号的)

C main()函数接收参数计数的整数和指向字符数组的指针

您的输出只是该指针包含的内存地址。 如果您将其转换为其他变量类型,它们也将包含“垃圾”


在正常情况下,如果可能的话,应该避免投射指针。

您将得到未定义的行为,这意味着任何事情发生都是合法的<代码>主必须声明为:

int main(void)
或作为:

int main(int arg, char** argv)
或者作为您的实现指定的某种形式

根据ISO C99标准第J.2节:

在以下情况下,该行为未定义:

  • 宿主环境中的程序不使用指定的形式(5.1.2.2.1)之一定义名为
    main
    的函数

正如其他人所指出的,行为是未定义的(因此任何事情都可能发生)

让我们看看三种“典型”行为。传递参数的三种常见方法是:

  • 堆积如山
  • 一般用途登记册
  • 特别用途登记册
英特尔x86系统大多使用第一种方法(但有时使用第二种或第三种)。基于MIPS的处理器大多使用第二种

如果系统使用一个或多个堆栈,通常的调用方法是:

  • 在调用者(一些操作系统提供的调用
    main
    的例程)中,推送参数,通常是从右向左,即按相反的顺序。堆栈推送通常(但不总是)看起来像
    *--sp=value在C中,堆栈指针从某个高位地址递减
  • 调用目标函数(
    main
  • 在目标函数中,从“堆栈”或“参数堆栈”或“当前线程堆栈”或系统使用的任何内容检索参数。由于按相反顺序推送,它们位于
    sp[0]
    sp[1]
    等地址。如果调用机制使用与参数传递机制相同的堆栈,索引可能从1或2开始,甚至更多(
    sp[2]
    是第一个参数,而
    sp[3]
    是第二个参数)
在这种情况下,
argc
可能是正确的,但是
argv
将错误解释调用者推送的内容,产生一个奇怪的
int
。如果基础系统足够复杂(检查类型),它可能会检测到调用方推送了类型为
char**
的值,但您正在访问类型为
int
的值,并给您带来某种运行时错误。不过,大多数简单系统更愿意尽可能快地给出错误答案,跳过类型检查。因此,您将得到一个奇怪的
int
,但它实际上是基于调用方试图传递的实际指针值(至少部分见下文)

如果系统使用通用寄存器(而不是或之前,使用GPRs的堆栈系统在使用多个参数时通常会退回堆栈,有时会将其用于所有可变函数,即使用
设施的函数),则调用方法更像这样:

  • 在调用者中,将参数(
    int argc
    value和
    char**argv
    value)移动到前两个参数寄存器中(例如,SPARC上的
    %o0
    %o1
    ,或MIPS上的
    $a0
    $a1
  • 调用目标函数
  • 在目标函数中,访问参数寄存器中的值
在这种情况下,代码的行为通常与基于堆栈的系统上的行为相同。它只是运行得更快,因为寄存器中的参数比内存中的参数需要更少的CPU周期。(这就是为什么某些英特尔编译器有时会在寄存器中传递一两个参数。)

但是,如果系统使用专用寄存器,我们会得到一个新的明显行为。让我们假设浮点值进入
f
寄存器(在某些SPARC系统上为真;x86具有MMX和SSE寄存器);指针值进入
a
寄存器(a la 680x0 cpu);整数值进入
d
寄存器(680x0,尽管实际上大多数680x0系统只使用“堆栈”,但我们假设有一个使用寄存器)。这次,调用
main
的东西需要传递一个整数,
argc
,以及一个指针,
argv
,因此它会这样做:

  • 将整数参数
    argc
    移动到数据r中
    int main(int arg, char** argv)
    
    printf("%c\n", **(char **)argv);