C语言中的指针和字符变量
我试图将C语言中的指针和字符变量,c,pointers,char,C,Pointers,Char,我试图将evil变量的内存位置存储在ptr变量中,但该变量不打印内存位置,而是打印变量中的值,而不是它的位置。ptr变量和&evil语法都打印相同的结果,即变量的值,而不是它在内存中的位置。有没有人能告诉我正确的方向,并帮助我确定在C中存储string/char变量的内存位置所需的语法 int main() { char *ptr; char evil[4]; memset(evil, 0x43, 4);//fill evil variable with 4 C's
evil
变量的内存位置存储在ptr
变量中,但该变量不打印内存位置,而是打印变量中的值,而不是它的位置。ptr
变量和&evil
语法都打印相同的结果,即变量的值,而不是它在内存中的位置。有没有人能告诉我正确的方向,并帮助我确定在C中存储string/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;
}
这是正常的,因为
printf
的第一个参数是一个格式说明符,它基本上是一个指向字符串的char*
。您的字符串将按原样打印,因为它不包含任何格式说明符
如果要将指针的值显示为地址,请使用%p
作为格式说明符,并将指针作为后续参数:
printf("%p", ptr);
但是,请注意,您的代码调用未定义行为(UB),因为您的字符串不是以null结尾的。很可能是因为“运气不好”
还请注意,要成为“正确的代码”,请在将指针发送到printf
时将其转换为void*
,因为不同类型的指针在某些平台上可能不同,并且C标准要求参数为指向void的指针。有关详细信息,请参阅此线程:
printf(“%p”,(void*)ptr);// 如果你想看到一个字符的地址-没有所有的数组/指针/衰减奇怪
int main()
{
char *ptr;
char evil;
evil = 4;
ptr = &evil;
printf("%p\n",(void*)ptr);
printf("%p\n",(void*)&evil);
return 0;
}
使用
导致未定义的行为,因为printf
的第一个参数必须是以null结尾的字符串。你的情况不是这样
有人能把我推到正确的方向吗
要打印地址,您需要在调用printf
时使用%p
格式说明符
printf("%p\n", ptr);
或
或
请参阅以了解它的所有使用方法。对于printf
,您需要
;对于memset
,您需要
int main()
您可以这样做,但是intmain(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个)元素的地址。这与数组对象本身的地址不同。它们在内存中的位置相同,但是&evil[0]
和&evil
的类型不同
你也可以这样写:
ptr = evil;
不能分配数组,但在大多数上下文中,数组表达式隐式转换为指向数组初始元素的指针
C语言中数组和指针之间的关系可能令人困惑。
规则1:数组不是指针。
第2条:阅读本手册第6节
printf
的第一个参数应该(几乎)始终是字符串文字,即格式字符串。如果您给它一个char数组变量的名称,并且它恰好包含%
个字符,那么可能会发生不好的事情。如果只是打印字符串,可以使用“%s”
作为格式字符串:
printf("%s\n", ptr);
(请注意,我添加了一个换行符,以便正确显示输出。)
除了ptr
没有指向字符串。根据定义,字符串以空('\0'
)字符结尾。你的邪恶
数组不是。(内存中的数组后面可能正好有一个空字节。不依赖于此。)
您可以使用字段宽度确定要打印的字符数:
printf("%.4s\n", ptr);
或者,为了避免必须多次写入同一个数字的容易出错的做法:
printf("%.*s\n", (int)sizeof evil, evil);
如果您想了解这一点,请为printf
查找一份好的文档
(或者,根据您正在做的事情,您可能应该首先安排evil
以null结尾。)
啊,现在我们有一些严重的未定义的行为。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;
}
C++标签!它消失了<非空终止字符串的code>printf()
永远不会有任何用处。数组在语言中有点不一致:evil
和&evil
的意思是相同的——这只适用于数组。另外,你很幸运,printf
在你的角色数组中没有显式的0-终止符。@leedinelcrocker:No,evil
和&evil
的意思不一样evil
是数组对象的名称;在大多数(但不是所有)上下文中,它隐式转换为其初始成员的地址&evil
是整个数组的地址,而不是其初始元素的地址;它的类型是char(*)[4]
,而不是char*
。建议阅读:@leednielcrocker:认为这是一种语言
printf(ptr);//prints 4 C's
printf("%s\n", ptr);
printf("%.4s\n", ptr);
printf("%.*s\n", (int)sizeof evil, evil);
printf(&evil);//prints 4 C's
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