我正在尝试将evil
变量的内存位置存储在ptr
变量中,但该变量不是内存位置,而是打印出变量中的值而不是它的位置。 ptr
变量和&evil
语法都打印相同的结果,即变量的值,而不是它在内存中的位置。有人可以请我按正确的方向推动我,并帮我确定在C中存储字符串/ char变量的内存位置所需的语法吗?
int main()
{
char *ptr;
char evil[4];
memset(evil, 0x43, 4);//fill evil variable with 4 C's
ptr = &evil[0];//set ptr variable equal to evil variable's memory address
printf(ptr);//prints 4 C's
printf(&evil);//prints 4 C's
return 0;
}
答案 0 :(得分:3)
这是正常的,因为printf
的第一个参数是格式说明符,它基本上是指向字符串的char*
。您的字符串将按原样打印,因为它不包含任何格式说明符。
如果要将指针的值显示为地址,请使用%p
作为格式说明符,并将指针作为后续参数:
printf("%p", ptr);
但是,请注意您的代码调用Undefined Behavior(UB),因为您的字符串不是以null结尾的。有可能是因为“失败”而无效终止。
另请注意,要将其设置为“正确代码”,请将指针发送到void*
时将其指向printf
,因为在某些平台上不同类型的指针可能不同,而C标准需要参数成为指向虚空的指针。有关详细信息,请参阅此主题:printf("%p") and casting to (void *)
printf("%p", (void*)ptr); // <-- C standard requires this cast, although it migh work without it on most compilers and platforms.
答案 1 :(得分:3)
#include <stdio.h>
需要printf
,#include <string.h>
需要memset
。
int main()
你可以侥幸成功,但int main(void)
更好。
{
char *ptr;
char evil[4];
memset(evil, 0x43, 4);//fill evil variable with 4 C's
如果您将0x43
替换为'C'
,这将更加清晰。它们都意味着相同的事情(假设基于ASCII的字符集)。更好的是,不要重复这个尺寸:
memset(evil, 'C', sizeof evil);
ptr = &evil[0];//set ptr variable equal to evil variable's memory address
这将ptr
设置为数组对象evil
的初始(第0个)元素的地址。这与数组对象本身的地址不同。它们在内存中的位置相同,但&evil[0]
和&evil
的类型不同。
您也可以将其写为:
ptr = evil;
您无法分配数组,但在大多数情况下,数组表达式会隐式转换为指向数组初始元素的指针。
C中数组和指针之间的关系可能令人困惑 规则1:数组是 不是 指针 规则2:阅读comp.lang.c FAQ的第6部分。
printf(ptr);//prints 4 C's
printf
的第一个参数应该(几乎)总是是一个字符串文字,即格式字符串。如果你给它一个char数组变量的名称,它碰巧包含%
个字符,那么Bad Things就会发生。如果您只是打印字符串,则可以使用"%s"
作为格式字符串:
printf("%s\n", ptr);
(请注意,我已添加换行符,以便正确显示输出。)
除ptr
没有指向字符串。根据定义,字符串由null('\0'
)字符终止。您的evil
数组不是。 (可能在内存中的数组之后恰好是一个空字节。不要依赖于它。)
您可以使用字段宽度来确定要打印的字符数:
printf("%.4s\n", ptr);
或者,为了避免多次写入相同数字的容易出错的做法:
printf("%.*s\n", (int)sizeof evil, evil);
如果您想了解这一点,请查找printf
的好文档。
(或者,根据您正在做的事情,也许您应该首先安排evil
为空终止。)
printf(&evil);//prints 4 C's
啊,现在我们有一些严重的未定义行为。 printf
的第一个参数是指向格式字符串的指针;它是const char*
类型的。 &evil
的类型为char (*)[4]
,指向4个char
元素数组的指针。您的编译器应该已经警告过您(格式字符串具有已知类型;以下参数没有,因此获取其类型是正确的)。如果似乎可以工作,那是因为&evil
指向与&evil[0]
相同的内存位置,并且不同的指针类型可能在您的系统上具有相同的表示形式,也许在阵列之后恰好有一个迷路'\0'
- 可能之前是你看不到的一些不可打印的角色。
如果要打印数组对象的地址,请使用%p
格式。它需要一个指针类型为void*
的参数,因此您需要将其强制转换:
printf("%p\n", (void*)&evil);
return 0;
}
将所有这些放在一起并添加一些花里胡哨的东西:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *ptr;
char evil[4];
memset(evil, 'C', sizeof evil);
ptr = &evil[0];
printf("ptr points to the character sequence \"%.*s\"\n",
(int)sizeof evil, evil);
printf("The address of evil[0] is %p\n", (void*)ptr);
printf("The address of evil is also %p\n", (void*)&evil);
return 0;
}
我系统的输出是:
ptr points to the character sequence "CCCC"
The address of evil[0] is 0x7ffc060dc650
The address of evil is also 0x7ffc060dc650
答案 2 :(得分:0)
如果你想看到一个char的地址 - 没有所有数组/指针/衰变奇数
int main()
{
char *ptr;
char evil;
evil = 4;
ptr = &evil;
printf("%p\n",(void*)ptr);
printf("%p\n",(void*)&evil);
return 0;
}
答案 3 :(得分:0)
使用
printf(ptr);//prints 4 C's
导致未定义的行为,因为printf
的第一个参数需要是一个以空字符结尾的字符串。在你的情况下,它不是。
有人可以请我朝正确的方向推动我
要打印地址,您需要在%p
的调用中使用printf
格式说明符。
printf("%p\n", ptr);
或
printf("%p\n", &evil);
或
printf("%p\n", &evil[0]);
有关可以使用的所有方式,请参阅printf
documentation。