【发布时间】:2025-11-27 05:50:02
【问题描述】:
我编写了一小段代码来了解如何遍历 char 指针数组和 2D 字符数组。我用过 1] 和 2] 在打印 o/p 只跟踪哪个代码块打印什么时,请忽略它们。
打印 o/p 的类似代码用于遍历 3 个不同(类型)的数组:-
a) 字符指针数组:char *argv[]
b) 字符指针数组:char *str[]
c) 二维字符数组:char strarr[][7]
我执行的基本操作如下: if char *foo[] then
A) foo 指向 foo 的第一个元素(字符串)(对此表示怀疑)
B) *++foo 指向 foo 的下一个元素的第一个字符
C) **++foo 给出 foo 的下一个元素的第一个字符
D) ++*foo 指向 foo 元素中的下一个字符
E) **++*foo 给出 foo 元素内的下一个字符
只有在 char *argv[] 的情况下才允许操作 A、B、C 和 D。 char *str[] 只允许操作 C & D;而二维数组 char strarr[][7] 不允许所有 A-D。
我明白为什么 char *str[] 允许 C 和 D 操作,而 char strarr[][7] 则不允许: 由于 char *str[] 是一个数组指针,并且它的元素(即地址到字符串的值)的值的增加是允许的,而在 char strarr[]2[7] 是元素的二维数组的情况下,它不可能增加其元素的地址。
纠正我的任何错误假设。
但我无法理解为什么 **++str、*++str 或 ++str 是不允许的,而 **++argv *++argv 或 ++argv 是允许的?
argv 和 str 都是 char 指针数组,那么为什么会有这种不同的行为呢? (str 指向 str[0] 那么为什么 ++str 会导致错误而不是指向 str[1]?) char *argv[] 是某种特殊类型的数组还是以其他方式/方法对其执行的操作?
当我编写 **++str、*++str 或 ++str 时,编译器会给出以下错误:
gcc -Wall -c "TestProg.c"(在目录中: /home/crownedeagle/Downloads/CDAC C-CAT/C - K&R 解决方案)TestProg.c: 在函数'main'中:TestProg.c:61:33: error: lvalue required as 递增操作数 printf("\n1]\n**++str = %c", **++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
【问题讨论】:
-
如果我理解这个问题,我相信这与数组作为参数传递给函数“衰减”到指针这一事实有关。 Why do arrays in C decay to pointers?
-
关于这种说法:
printf("\n&(str[0]) = %p", &(str[0]));这是试图获取地址的地址。编译器输出:`71:28: 警告:格式“%p”需要“void *”类型的参数,但参数 2 的类型为“char **”[-Wformat=] -
关于这种声明:
printf("\n&(strarr[0]) = %p", &(strarr[0]));这是试图获取地址的地址编译器输出::94:29: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘char (*)[7]’ [-Wformat=] -
对于 OP 发布的代码,编译器会输出 15 个警告(如上述 2 个 cmets 所示)。编译时,始终启用警告,然后修复这些警告。 (对于
gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11)注意:其他编译器使用不同的选项来产生相同的结果