C中的指针和字符变量

时间:2017-01-05 00:50:41

标签: c pointers char

我正在尝试将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;
}

4 个答案:

答案 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