Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';C将地址转换为int的规则是什么?_C - Fatal编程技术网

什么';C将地址转换为int的规则是什么?

什么';C将地址转换为int的规则是什么?,c,C,我是C语言的初学者,今天我在学习指针部分,我发现我可以直接打印地址,当使用正确的类型转义符时,我甚至可以打印存储在该内存地址中的预期值 后来,我做了一些实验: ##### CODE PART ###### #include <stdio.h> // Define several variable types, macros, and functions about standard input/output. int main () { char my_string[]

我是C语言的初学者,今天我在学习指针部分,我发现我可以直接打印地址,当使用正确的类型转义符时,我甚至可以打印存储在该内存地址中的预期值

后来,我做了一些实验:

##### CODE PART ######
#include <stdio.h>  // Define several variable types, macros, and functions about standard input/output.

int main () {
    char my_string[] = "address test";
    printf("%s\n", &my_string);
    printf("%p\n", &my_string);
    printf("%d\n", &my_string);
    printf("%x\n", &my_string);
    printf("\n");

    char *p = "pointer string test";
    printf("%s\n", p);
    printf("%p\n", p);
    printf("%d\n", p);
    printf("\n");

    char *p2 = 'p';
    printf("%c\n", p2);
    printf("%p\n", p2);
    printf("%d\n", p2);
    return 0;
}


##### OUTPUT #####
address test
0x7fff58778a7b
1484229243
58778a7b

pointer string test
0x107487f87
122191751

p
0x70
112
代码部分###### #包括//定义几个关于标准输入/输出的变量类型、宏和函数。 int main(){ char my_string[]=“地址测试”; printf(“%s\n”&我的字符串); printf(“%p\n”&我的字符串); printf(“%d\n”&我的字符串); printf(“%x\n”&我的字符串); printf(“\n”); char*p=“指针字符串测试”; printf(“%s\n”,p); printf(“%p\n”,p); printf(“%d\n”,p); printf(“\n”); char*p2='p'; printf(“%c\n”,p2); printf(“%p\n”,p2); printf(“%d\n”,p2); 返回0; } #####输出##### 地址测试 0x7fff58778a7b 1484229243 58778a7b 指针字符串测试 0x107487f87 122191751 P 0x70 112 起初我不太了解
%d
格式输出的行为,但经过更多的观察和实验之后。我发现
%d
正在转换内存地址的部分十六进制值

但是对于
my_字符串的地址
它省略了
0x7fff
部分,对于
p
的地址它省略了
0x10
部分,对于
p2
它省略了
0x
部分。在我的认知中,
0x
是十六进制值的头符号

但是,我怎么知道在将内存地址转换为int时,C会省略多少位,就像在
my_string
p
的示例中一样



PS:我的系统版本是OSX10.10,没有规则。这不包括在C标准中。你的代码会导致。你在整个项目中观察到的任何结果都是毫无意义的

使用
printf
时,必须自己将参数转换为正确的类型

printf("%d\n", &my_string);
printf("%x\n", &my_string);
是未定义行为的原因。格式说明符和参数类型必须匹配,
printf
才能正常工作。有关有效格式说明符及其应用的数据类型的列表,请参阅

以下几行也有同样的问题

printf("%d\n", p);

printf("%c\n", p2);
printf("%d\n", p2);
线路

char *p2 = 'p';
将表示字符
'p'
的整数值指定给
p2
。但是,这不是一个有效的地址

可用于固定指针的整数类型有
intptr\u t
uintpr\u t
。因此,您可以使用:

char my_string[] = "address test";
intptr_t ptr = &my_string;
但是,不能使用
%d
格式说明符打印该值。您需要使用:

printf("%" SCNdPTR "\n", ptr);
把它打印出来

查看更多详细信息。

C标准(ISO/IEC 9899:2011)对指针和整数之间的转换有如下规定:

6.3转换 6.3.2.3指针 ^5整数可以转换为任何指针类型。除非前面指定,否则结果是实现定义的,可能没有正确对齐,可能没有指向引用类型的实体,可能是陷阱表示。67)

^6任何指针类型均可转换为整数类型。除非前面指定,否则结果是实现定义的。如果结果不能用整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内

67)用于将指针转换为整数或将整数转换为指针的映射函数旨在 与执行环境的寻址结构保持一致

请注意,指针和整数之间的转换行为是实现定义的,而不是未定义的。但是,除非使用的整数类型是
uintpr\u t
intptr\u t
(从
-或
),否则如果指针的大小与整数类型不匹配,则可能会看到截断效果。如果您在32位和64位系统之间移动代码,您将在某个地方遇到问题

在代码中,您有64位指针(因为您在Mac OS X 10.10上,需要显式指定
-m32
,以获得32位构建,但您的结果与64位构建是一致的)。当您使用
%d
%x
转换规范将这些指针传递到
printf()
时,您正在请求
printf()
打印32位数量,因此它将格式化传递的64位中的32位。行为不明确;从本质上讲,您没有得到转换,但是调用代码(在
main()
)将64位指针推送到堆栈上,而被调用代码(
printf()
)从堆栈中读取32位的量。如果您请求对
printf()
的单个调用应打印多个值(例如
printf(“%d%x\n”,p,p);
),您将得到更令人惊讶的结果

您应该使用以下选项进行编译:

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -Werror …
使用这些选项,您的代码将无法编译;编译器会抱怨格式字符串和传递的值之间不匹配。当我将您的代码保存到一个文件
noise.c
中,并使用
clang
编译它时(来自运行在Mac OS X 10.10.5上的XCode 7.2),我得到:


使用严格的警告编译,并注意这些警告。

没有像“十六进制值”这样的东西。数字就是数量。十进制和十六进制只是使用不同约定表示数字。人们也可以用罗马数字来表示数字,其值仍然保持不变

变量的地址是一个概念,而不是一个物理对象。在当前的操作系统和CPU架构上,这通常是一个(大)数字,但这并不是一成不变的

根据编译器及其编译的代码,变量可以存储在内存中(其地址看起来像一个大整数),也可以不存储。编译器可以优化代码并在CPU寄存器中存储临时变量;在这种情况下,它不会
$ /usr/bin/clang -O3 -g  -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror noise.c -o noise
noise.c:5:20: error: format specifies type 'char *' but the argument has type 'char (*)[13]'
      [-Werror,-Wformat]
    printf("%s\n", &my_string);
            ~~     ^~~~~~~~~~
noise.c:7:20: error: format specifies type 'int' but the argument has type 'char (*)[13]' [-Werror,-Wformat]
    printf("%d\n", &my_string);
            ~~     ^~~~~~~~~~
noise.c:8:20: error: format specifies type 'unsigned int' but the argument has type 'char (*)[13]'
      [-Werror,-Wformat]
    printf("%x\n", &my_string);
            ~~     ^~~~~~~~~~
noise.c:14:20: error: format specifies type 'int' but the argument has type 'char *' [-Werror,-Wformat]
    printf("%d\n", p);
            ~~     ^
            %s
noise.c:17:11: error: incompatible integer to pointer conversion initializing 'char *' with an expression of
      type 'int' [-Werror,-Wint-conversion]
    char *p2 = 'p';
          ^    ~~~
noise.c:18:20: error: format specifies type 'int' but the argument has type 'char *' [-Werror,-Wformat]
    printf("%c\n", p2);
            ~~     ^~
            %s
noise.c:20:20: error: format specifies type 'int' but the argument has type 'char *' [-Werror,-Wformat]
    printf("%d\n", p2);
            ~~     ^~
            %s
7 errors generated.
$