当前位置: 首页 > 知识库问答 >
问题:

为什么如果数组是char*str[],而如果是char*argv[](main函数的参数之一),++str操作会导致错误?

魏兴邦
2023-03-14

a)字符指针数组:char*argv[]

b)字符指针数组:char*str[]

c)二维字符数组:char strarr[][7]

B)*++foo指向foo下一个元素的第一个字符

C)**++foo给出foo的下一个元素的第一个字符

D)++*foo指向foo元素中的下一个字符

但我不明白为什么不允许**++str、*++str或++str的操作,而允许**++argv*++argv或++argv?

argv和str都是char指针数组,那么为什么会有这种不同的行为呢?(str指向str[0],那么为什么++str会导致错误,而不是指向str[1]?)char*argv[]是某种特殊类型的数组还是以其他方式/方法对其执行的操作?

当我编写**++str、*++str或++str时,编译器会给出以下错误:

//Pointer of Array and Array Pointer Experimentation

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>

int main(int argc, char *argv[])
{
    int i;
    if (argc == 7)
    {
        printf("\n");
        for (i = 0; i < argc; i++)
            printf("%s\t\t%p\n", argv[i], argv[i]);

        printf("\n0]\n**argv = %c", **argv);
        printf("\n*argv = %s", *argv);

        printf("\n1]\nargv = %p", argv);
        printf("\n*argv = %s", *argv);
        printf("\n**++argv = %c", **++argv);
        printf("\nargv = %p", argv);
        printf("\n*argv = %s", *argv);
        printf("\n**++argv = %c", **++argv);
        printf("\nargv = %p", argv);
        printf("\n*argv = %s", *argv);      

        printf("\n2]\nargv = %p", argv);
        printf("\n&(argv[0]) = %p", &(argv[0]));
        printf("\n*argv = %p", *argv);
        printf("\n&(**argv) = %p", &(**argv));

        printf("\n*++*argv = %c", *++*argv);
        printf("\n*argv = %s", *argv);

        printf("\nargv = %p", argv);
        printf("\n&(argv[0]) = %p", &(argv[0]));
        printf("\n*argv = %p", *argv);
        printf("\n&(**argv) = %p", &(**argv));

        printf("\nargv[0] = %s", argv[0]);

        printf("\n\n");

        for (i = 0; i < argc; i++)
            printf("%s\t\t%p\n", argv[i], argv[i]);
    }

    char *str[] = {"ABCDEF", "HIJKLM", "OPQRST", "VWXYZA", "123456"};

    printf("\n");
    for (i = 0; i < 5; i++)
            printf("%s\t\t%p\n", str[i], str[i]);

    printf("\n0]\n**str = %c", **str);
    printf("\n*str = %s", *str);

    //printf("\n1]\n**++str = %c", **++str);
    //printf("\n*str = %s", *str);

    printf("\n1]\nstr = %p", str);
    printf("\n&(str[0]) = %p", &(str[0]));
    printf("\n*str = %p", *str);
    printf("\n&(**str) = %p", &(**str));

    printf("\n*++*str = %c", *++*str);
    printf("\n*str = %s", *str);

    printf("\nstr = %p", str);
    printf("\n&(str[0]) = %p", &(str[0]));
    printf("\n*str = %p", *str);
    printf("\n&(**str) = %p", &(**str));

    printf("\nstr[0] = %s", str[0]);

    printf("\n\n");

    for (i = 0; i < 5; i++)
            printf("%s\t\t%p\n", str[i], str[i]);

    char strarr[][7] = {"ABCDEF", "HIJKLM", "OPQRST", "VWXYZA", "123456"};

    printf("\n");
    for (i = 0; i < 5; i++)
            printf("%s\t\t%p\n", strarr[i], strarr[i]);

    printf("\n0]\n**strarr = %c", **strarr);
    printf("\n*strarr = %s", *strarr);

    //printf("\n1]\n**++strarr = %c", **++strarr);
    //printf("\n*strarr = %s", *strarr);

    printf("\n1]\nstrarr = %p", strarr);
    printf("\n&(strarr[0]) = %p", &(strarr[0]));
    printf("\n*strarr = %p", *strarr);
    printf("\n&(**strarr) = %p", &(**strarr));

    //printf("\n*++*strarr = %c", *++*strarr);
    printf("\n*strarr = %s", *strarr);

    printf("\nstrarr = %p", strarr);
    printf("\n&(strarr[0]) = %p", &(strarr[0]));
    printf("\n*strarr = %p", *strarr);
    printf("\n&(**strarr) = %p", &(**strarr));

    printf("\nstrarr[0] = %s", strarr[0]);

    printf("\n\n"); 

    for (i = 0; i < 5; i++)
            printf("%s\t\t%p\n", strarr[i], strarr[i]);

    return 0;   
}
crownedeagle@EagleNest:~/C - K&R Solutions$ ./TestProg abcdef hijklm opqrst vwxyza 123456 789012

    ./TestProg    0x7ffd61c027c7
    abcdef        0x7ffd61c027d2
    hijklm        0x7ffd61c027d9
    opqrst        0x7ffd61c027e0
    vwxyza        0x7ffd61c027e7
    123456        0x7ffd61c027ee
    789012        0x7ffd61c027f5

    0]
    **argv = .
    *argv = ./TestProg
    1]
    argv = 0x7ffd61c01c98
    *argv = ./TestProg
    **++argv = a
    argv = 0x7ffd61c01ca0
    *argv = abcdef
    **++argv = h
    argv = 0x7ffd61c01ca8
    *argv = hijklm
    2]
    argv = 0x7ffd61c01ca8
    &(argv[0]) = 0x7ffd61c01ca8
    *argv = 0x7ffd61c027d9
    &(**argv) = 0x7ffd61c027d9
    *++*argv = i
    *argv = ijklm
    argv = 0x7ffd61c01ca8
    &(argv[0]) = 0x7ffd61c01ca8
    *argv = 0x7ffd61c027da
    &(**argv) = 0x7ffd61c027da
    argv[0] = ijklm

    ijklm         0x7ffd61c027da
    opqrst        0x7ffd61c027e0
    vwxyza        0x7ffd61c027e7
    123456        0x7ffd61c027ee
    789012        0x7ffd61c027f5
    (null)        (nil)
    XDG_VTNR=7    0x7ffd61c027fc

    ABCDEF        0x400dfa
    HIJKLM        0x400e01
    OPQRST        0x400e08
    VWXYZA        0x400e0f
    123456        0x400e16

    0]
    **str = A
    *str = ABCDEF
    1]
    str = 0x7ffd61c01b80
    &(str[0]) = 0x7ffd61c01b80
    *str = 0x400dfa
    &(**str) = 0x400dfa
    *++*str = B
    *str = BCDEF
    str = 0x7ffd61c01b80
    &(str[0]) = 0x7ffd61c01b80
    *str = 0x400dfb
    &(**str) = 0x400dfb
    str[0] = BCDEF

    BCDEF         0x400dfb
    HIJKLM        0x400e01
    OPQRST        0x400e08
    VWXYZA        0x400e0f
    123456        0x400e16

    ABCDEF        0x7ffd61c01b50
    HIJKLM        0x7ffd61c01b57
    OPQRST        0x7ffd61c01b5e
    VWXYZA        0x7ffd61c01b65
    123456        0x7ffd61c01b6c

    0]
    **strarr = A
    *strarr = ABCDEF
    1]
    strarr = 0x7ffd61c01b50
    &(strarr[0]) = 0x7ffd61c01b50
    *strarr = 0x7ffd61c01b50
    &(**strarr) = 0x7ffd61c01b50
    *strarr = ABCDEF
    strarr = 0x7ffd61c01b50
    &(strarr[0]) = 0x7ffd61c01b50
    *strarr = 0x7ffd61c01b50
    &(**strarr) = 0x7ffd61c01b50
    strarr[0] = ABCDEF

    ABCDEF        0x7ffd61c01b50
    HIJKLM        0x7ffd61c01b57
    OPQRST        0x7ffd61c01b5e
    VWXYZA        0x7ffd61c01b65
    123456        0x7ffd61c01b6c

共有1个答案

谭泉
2023-03-14

在此函数声明中

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

编译器将具有未知大小类型的数组的参数调整为指向元素类型的指针。也就是说,这个声明相当于

int main(int argc, char **argv )

因此,在函数中,您处理的是一个指针,您可以应用增量或赋值运算符。

void f( int a[100] );
void f( int a[10] );
void f( int a[] );
void f( int *a );

7将参数声明为“类型数组”应调整为“类型限定指针”,其中类型限定符(如果有)是在数组类型派生的[和]中指定的。如果关键字static也出现在数组类型派生的[and]中,那么对于函数的每次调用,对应的实际参数的值应提供对数组的第一个元素的访问,该数组的元素至少与大小表达式指定的元素一样多。

在本声明中

char *str[] = {"ABCDEF", "HIJKLM", "OPQRST", "VWXYZA", "123456"};

声明了char*[5]类型的数组。数组是不可修改的L值。因此不能应用于数组、增量或赋值运算符。

 类似资料:
  • 描述 (Description) C库函数char *gets(char *str)从stdin读取一行并将其存储到str指向的字符串中。 当读取换行符或达到文件结尾时(以先到者为准),它会停止。 声明 (Declaration) 以下是gets()函数的声明。 char *gets(char *str) 参数 (Parameters) str - 这是指向存储C字符串的字符数组的指针。 返回值

  • 描述 (Description) C库函数char *tmpnam(char *str)生成并返回一个不存在的有效临时文件名。 如果str为null,则它只返回tmp文件名。 声明 (Declaration) 以下是tmpnam()函数的声明。 char *tmpnam(char *str) 参数 (Parameters) str - 这是指向字符数组的指针,其中建议的tempname将存储为C

  • 描述 (Description) C库函数char *strtok(char *str, const char *delim)使用分隔符delim将字符串str分解为一系列标记。 声明 (Declaration) 以下是strtok()函数的声明。 char *strtok(char *str, const char *delim) 参数 (Parameters) str - 修改此字符串的内容

  • 描述 (Description) C库函数char *strrchr(const char *str, int c)通过参数str指向的字符串中最后一次出现的字符c (unsigned char)。 声明 (Declaration) 以下是strrchr()函数的声明。 char *strrchr(const char *str, int c) 参数 (Parameters) str - 这是C

  • 描述 (Description) C库函数char *strchr(const char *str, int c)搜索参数str指向的字符串中第一次出现的字符c (unsigned char)。 声明 (Declaration) 以下是strchr()函数的声明。 char *strchr(const char *str, int c) 参数 (Parameters) str - 这是要扫描的C

  • 描述 (Description) C库函数double strtod(const char *str, char **endptr)将参数str指向的字符串转换为浮点数(double类型)。 如果endptr不为NULL,则指向转换中使用的最后一个字符后的字符的指针将存储在endptr引用的位置。 声明 (Declaration) 以下是strtod()函数的声明。 double strtod(c