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

Ste*_*n K 6 c pointers sizeof argv

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

让我们说我有一个名为"test.c"的ac程序,我想找到数组中的空格数,用户输入的单词作为参数.例如,"./ 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;
}
Run Code Online (Sandbox Code Playgroud)

打印结果:" buf10的大小为:10 ".这是有道理的,因为我选择了一个char数组.在C中,char的大小是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;
}
Run Code Online (Sandbox Code Playgroud)

使用"./test Hello_SO"进行输出:

argv[1] has the value: Hello_SO
strlen of argv[1] is: 8
sizeof of argv[1] is: 4
Run Code Online (Sandbox Code Playgroud)

字符串长度是有意义的,因为它应该是9但减去"\ 0"使得8.

但是我不明白为什么sizeof返回4(指针的大小).我知道*argv []可以被认为是**argv.但我已经说明了这一点.在我的第一个例子中,我打印"buf",但在这里我打印"argv [1]".我知道我可以通过使用strlen轻松得到答案,但正如我之前所说,这只是概念性的.

Rya*_*ing 4

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

int arr[10];
assert(sizeof arr == (sizeof(int) * 10));
int *ip;
assert(sizeof ip == sizeof(int*));
Run Code Online (Sandbox Code Playgroud)

arr上面的类型是int[10]. 了解数组类型和指针之间差异的另一种方法是尝试为它们赋值。

int i;
ip = &i; // sure, fine
arr = &i; // fails, can't assign to an int[10]
Run Code Online (Sandbox Code Playgroud)

数组不能被赋值。

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

int f(int arr[10]) {
    int x;
    arr = &x; // fine, because arr is actually an int*
    assert(sizeof arr == sizeof(int*));
}
Run Code Online (Sandbox Code Playgroud)

为了解决为什么不能使用sizeof argv[1]并获取字符串的大小(加上 1 \0)的问题,这是因为它是一个参差不齐的数组。在这种情况下,第一维和第二维的大小都是未知的。 sizeof在这种情况下,其行为类似于编译时操作,并且直到运行时才知道字符串的长度。

考虑以下程序:

#include <stdio.h>

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

为此生成的程序集是:

.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
Run Code Online (Sandbox Code Playgroud)

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