这是第一个代码:
#include <stdio.h>
#include <stdlib.h>
void test(int,int);
int main()
{
int p=23,f=24;
test(&p,&f);
printf("%d %d\n",p,f);
return 0;
}
void test(int q,int g)
{
q=q+q;
g=g+g;
}
此代码生成TYPE MISMATCH ERROR可能是因为我在函数调用期间将变量的地址作为参数传递,而形式参数不是指针。
这是第二个代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int p=23,f=24,q,g;
q=&p;
g=&f;
printf("%d %d\n",q,g);
return 0;
}
第二个代码的输出是
1638220 1638228
在此代码中,q
和g
不是指针。那么为什么他们提供正确的输出,而不是错误?
答案 0 :(得分:3)
注意:
您的评论:“第二个代码打印正确的p和f地址,其中第一个代码给出错误”在各个级别上都是错误的。
您声称您的printf
语句打印变量的内存地址?错了,它没有这样的事情。不能。不可能。不会发生。
要打印变量的内存地址,printf
语句应如下所示:
printf("p @ %p\nf @ %p\n", (void *) &p, (void *) &f);//one of few cases where you SHOULD cast
您只打印一个数字:
printf("%d %d", p, f);
那些不是同一件事。请看一下这个答案底部的例子,但也要读一下中间的位
嗯,您将q
和g
声明为整数,并为其分配了p
和f
的内存地址。它是未定义的行为(即标准不确定如何处理它,因此它可能会因编译器而异,WCS:您的应用程序崩溃)。在你的情况下,我会说这种情况发生了:
基本上,内存地址看起来像这样:
0x213ABC
十六进制值,可以解释为数字,因此无法阻止您将其分配给char
或size_t
或其他任何内容。
HOWEVER ,如果您使用-Wall
编译代码,则会收到有关从int *
类型到int
的隐式转换的警告。除此之外,你“安全”。请注意:程序的输出将是不可预测的,因此毫无意义。
第一个代码段包含一个更大的问题:您将一个值传递给一个只是不存在的函数! test
函数无法处理您传递的内容,因为它的原型显示它需要2个整数,而不是2个指针
test(&p,&f);
//to:
test((int) &p,(int) &f);
但是,它 编译,as you can see here,但结果是不可预测的(未定义的行为)。
调用test(&p, &f)
时,您调用的函数应如下所示:
void test(int *, int *)
然而,这个签名/原型无处可寻,因此编译器无法继续。将内存地址转换为int会改变所有这些,并让编译器知道该函数看起来像void test (int, int)
,并且该函数 存在,因此它会编译。
这样想:
你:你的电话号码是什么? 我:abc
你:那不是电话号码 我:我的意思是1-11-111(短信的数字键,那些日子)
这就是你在这里做的事情:
test(&p, &f);
//compiler: can't find function test(int *, int *)
//you: I expect you to call test(int, int), and implicitly cast the pointers to ints
这不是C的工作原理。
注意:
正如我在内容中指出的那样:将指针分配/转换为 int 是未定义的行为(即:这些操作的结果未由标准定义)
打印指针的示例程序,以及应打印的unsigned long和int:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int p = 2, f = 4, q;
q = (int) &f;
printf("p @ %p\nf @ %p\n", (void *) &p, (void *) &f);
//int is too small for 64bit address, use unsigned long here
printf("%d != %ul != %p\n", q, &f, (void *) &f);
return EXIT_SUCCESS;
}
当我通过this codepad运行时,我得到了以下输出:
p @ 0xbf70e1d8
f @ 0xbf70e1d4
-1083121196 != 3211846100l != 0xbf70e1d4