C 使用sizeof查找argv中字符串的大小

C 使用sizeof查找argv中字符串的大小,c,pointers,sizeof,argv,C,Pointers,Sizeof,Argv,在这一点上,这更多的是一个概念性的问题,而不是一个实际的问题,但它确实困扰着我 假设我有一个名为“test.c”的c程序,我想找出数组中用户键入的单词作为参数的空格数。例如,“/test.c test_run”应该打印9,因为有8个字符,然后是一个空终止字符。当我尝试在argv上使用sizeof时,尽管我遇到了一些麻烦 int main(int argc, char *argv[]) { char buf10[10]; printf("The size of buf10 is:

在这一点上,这更多的是一个概念性的问题,而不是一个实际的问题,但它确实困扰着我

假设我有一个名为“test.c”的c程序,我想找出数组中用户键入的单词作为参数的空格数。例如,“/test.c test_run”应该打印9,因为有8个字符,然后是一个空终止字符。当我尝试在argv上使用sizeof时,尽管我遇到了一些麻烦

int  main(int argc, char *argv[]) {
    char buf10[10];
    printf("The size of buf10 is: %i.\n", sizeof(buf10));
    return 0;
}
打印结果:“buf10的大小为:10.”。这很有意义,因为我选择了一个字符数组。在C语言中,字符的大小是1字节。如果我选择int,这个数字将是4

现在我的问题是为什么我不能用argv做这个

int  main(int argc, char *argv[]) {
    printf("argv[1] has the value: %s\n", argv[1]);
    printf("strlen of argv[1] is: %i\n", strlen(argv[1]));
    printf("sizeof of argv[1] is: %i\n", sizeof(argv[1]));
    return 0;
}
与“/test Hello_SO”一起运行会给出以下输出:

argv[1] has the value: Hello_SO
strlen of argv[1] is: 8
sizeof of argv[1] is: 4
字符串长度有意义,因为它应该是9,但减去“\0”表示8


但是,我不明白为什么sizeof返回4(指针的大小)。我理解*argv[]可以被认为是**argv。但我已经解释过了。在我的第一个示例中,我打印“buf”,但在这里我打印“argv[1]”。我知道我可以通过使用strlen很容易地得到答案,但正如我前面所说的,这只是概念性的

编译时已知buf10变量是由十个字符组成的(连续)数组。其他指针是动态分配的,是指向字符的指针。这就是为什么会得到字符数组的大小与(char*)的大小之比。

指针和数组不是一回事,尽管它们在许多情况下非常相似
sizeof
是一个关键区别

int arr[10];
assert(sizeof arr == (sizeof(int) * 10));
int *ip;
assert(sizeof ip == sizeof(int*));
上面的
arr
类型是
int[10]
。查看数组类型和指针之间差异的另一种方法是尝试分配给它们

int i;
ip = &i; // sure, fine
arr = &i; // fails, can't assign to an int[10]
无法将数组分配给

最让人困惑的是,当你有一个数组作为函数参数时,它实际上和有一个指针是一样的

int f(int arr[10]) {
    int x;
    arr = &x; // fine, because arr is actually an int*
    assert(sizeof arr == sizeof(int*));
}
为了解决为什么不能使用argv[1]的
sizeof并获取字符串的大小(加上
\0
的1),这是因为它是一个参差不齐的数组。在这种情况下,第一个维度和第二个维度的大小都未知<在本例中,code>sizeof
的行为类似于编译时操作,字符串的长度直到运行时才知道

考虑以下计划:

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("%zu\n", sizeof argv[1]);
}

如您所见,
sizeof argv[1]
的结果是在编译时完成的,上面没有计算字符串的长度。我是64位的,所以我的指针是8字节。

听起来你可能已经回答了你自己的问题。
argv[1]
有类型
char*
,所以
sizeof argv[1]
意味着
sizeof(char*)
。sizeof就是这么做的。但是为什么buf10打印10而argv[1]不打印9呢。buf10也是一个指针,不是吗?
buf10
是一种数组类型,不是指针。@StevenK这两种类型在编译时都可用;问题是编译器是否会在这种情况下应用优化。您应该使用
%zu
打印
大小\u t
值。。。好吧,我一开始误解了你的问题。也许有一个更具启发性的例子:
char*fubar=“hello world”
与fubar相比,您希望
sizeof NULL
产生什么样的值?
sizeof
是否应尝试跟随指针以找出所指向对象的大小?如果是这样的话,那么第一个例子肯定是无效的,对吗?那么char buf10[10]=“Hello”和char buf10[]=“Hello”之间是否有区别?后者将根据存储“Hello”所需的空间来计算数组的长度。因此,将是6的大小。但它仍然是一个数组。如果您确实执行了
const char*s=“Hello”
,那么
sizeof s
将是
sizeof(char*)
造成混淆的真正原因是您不能将数组作为函数参数——如果您将函数参数声明为数组,编译器会将其默默地转换为指针,“非常有用”隐藏任何误解并导致这些错误。@chrisdd是的,但不要忘记具有不同规则的多维数组。在C中没有多维数组这样的东西——只有数组数组数组,当用作参数时它们会变成指针,就像任何其他数组一样。另外还有数组数组和指针数组之间的混淆,尽管它们可以用相同的语法访问,但它们是完全不同的。@chrisddy不管是否称它们为多维数组,我只是指出
intf(inta[][5]){printf(“%zu\n”,sizeof a[0]);}
prints
sizeof(int)*5
不是
sizeof(int*)
@StevenK我想你的意思是
int*const
.LC0:
    .string "%zu\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB3:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $8, %esi        # this 8 is the result of sizeof
    movl    $.LC0, %edi     # the format string
    movl    $0, %eax
    call    printf          # calling printf
    movl    $0, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc