【发布时间】:2015-05-06 21:17:25
【问题描述】:
来自 Python,我会简单地使用 type() 来找出对象的类型,C,缺乏自省,迫使我更好地掌握它的数据类型、它们的相关性和指针,然后再继续了解更多进阶话题。 这是一件好事。所以我有以下一段代码,我将通过各种方式对其进行调整并尝试理解产生的行为:
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; argv[1][i] != '\0'; i++) {
printf("%d\n", argv[1][i]);
char letter = argv[1][i];
switch(letter) {
case 2:
printf("%d: 2\n", i);
break;
如果我运行它并将数字 2 作为单个参数传递,则不会发生任何事情。我的理解是,因为我已将 argv1[i] 定义为 char,将其与 2(一个 int)进行比较将返回 false,因此不会调用代码。事实上,如果我将大小写从 2 更改为“2”,代码确实会被调用。有道理,但它引出了我的第一个问题:
Q1. 我在很多地方读到过,对于 C,字符和整数本质上是一回事。 那么为什么 C 不“知道”作为参数传递的 2 应该被解释为整数而不是字符串?毕竟,C 允许我使用 %d 字符串字符格式化程序。
如果我随后将变量 letter 的类型从 char 更改为 int:
int letter = argv[1][i];
...我仍然得到与第一个变体相同的行为(即没有发生任何事情),即使现在我显然正在将 int 与 case 语句中的 int 进行比较。这使我推测,尽管我现在将 letter 定义为 int,但 C 仍在命令行上将其作为 char 读取,并且仅将其称为 int 不足以改变它从后续程序流程的角度来看类型。
第二季度。以上推理正确吗?
所以现在我想如果我使用 atoi() 将字母的类型更改为 int,那么一切都会好起来的。所以:
int letter = atoi(argv[1][i]);
当我现在尝试编译时,我得到:
Switch.c:14:27: warning: incompatible integer to pointer conversion passing
'char' to parameter of type 'const char *'; take the address with &
[-Wint-conversion]
int letter = atoi(argv[1][i]);
^~~~~~~~~~
&
/usr/include/stdlib.h:132:23: note: passing argument to parameter here
int atoi(const char *);
然后我查看 atoi() 的文档,发现它只能用于转换字符串(更准确地说,是 const char *),而不是字符。我会认为,因为 char * 只是一个字符序列,所以 atoi() 可以同时使用这两个字符。显然,对于 char 没有等价的 atoi(),而只有解决方法,例如描述的 here。
无论如何,我决定接受警告的说明,并在值之前放置一个 & 号(知道这意味着一个内存地址,但还不知道为什么建议它)。所以:
int letter = atoi(&argv[1][i]);
当我这样做时,它会编译。现在这个最终形式的程序 - 将字母定义为 int,case 语句与 int 进行比较,并且 atoi 被传递地址而不是 argv[1][i] 的值 - 成功运行。
但我不知道为什么,所以我把它剥离出来,通过打印argv[1][i] 和&argv[1][i] 的值来测试它们。我观察到程序只有在我使用 %s 字符串格式化程序来打印 &argv[1][i] 时才能编译,因为它告诉我 &argv[1][i] 是一个字符 *。
第三季度。为什么&argv[1][i],内存中的地址,char *?
在我的打印输出中,我观察到&argv[1][i] 和argv[1][i] 的值是相同的,即:2。所以:
第四季度。为什么编译器不允许我使用argv[1][i],如果它的值与&argv[1][i] 的值没有区别?
Q5。每当我在 C 程序中打印内存地址时,它总是一个长数字,例如 1246377222。为什么在这种情况下内存地址 == 值?
毫无疑问,会有人反对这个庞大的帖子应该分成不同的帖子和不同的问题,但我认为反复试验的流程以及您提供的答案不仅会帮助我,还会帮助其他人了解 C 的这些方面。也可以随意为帖子建议一个更好的标题。
非常感谢。
【问题讨论】:
-
您要求的是 C 编程课程的整个介绍部分。一个问题相当多。
-
atoi()存在是有原因的 - 请参阅 here -
是的,如果只允许我回答其中一个问题,那就是 Q5。我邀请你阐明一些观点。非常感谢。
-
您一次只能问一个问题。我试图回答标题中的问题。
-
这里有很多好问题!
标签: c pointers type-conversion pass-by-reference memory-address