C 为什么存储在整数中的字符串会被打印出来?
为什么即使k的数据类型是整数,这个hello也会打印出来?您的代码调用 您正在尝试使用字符串文字(字符*)初始化C 为什么存储在整数中的字符串会被打印出来?,c,string,integer,C,String,Integer,为什么即使k的数据类型是整数,这个hello也会打印出来?您的代码调用 您正在尝试使用字符串文字(字符*)初始化int。这没有任何意义,而且会引起争议 您正试图使用%s打印int,这需要一个char*。这也没有意义,需要调用。这里,hello是一个字符串文本,因此它存储在可执行文件的文本部分(沿着代码),当您将其分配给整数时,实际上指向文本的指针将分配给整数。由于两者通常大小相同(4字节),因此不会出现堆栈溢出之类的问题。 printf将正常工作,因为它将转到存储在变量中的地址(此处为k),并将
int
。这没有任何意义,而且会引起争议
您正试图使用
%s
打印int
,这需要一个char*
。这也没有意义,需要调用。这里,hello
是一个字符串文本,因此它存储在可执行文件的文本部分(沿着代码),当您将其分配给整数时,实际上指向文本的指针将分配给整数。由于两者通常大小相同(4字节),因此不会出现堆栈溢出之类的问题。
printf将正常工作,因为它将转到存储在变量中的地址(此处为k),并将打印字符串,直到找到字符串\0
的结尾
注意-所做的是错误的,并且提供了不可取的结果
结果(忽略警告在某些情况下是犯罪,这是其中之一
这些案件)
关于它为什么为您打印字符串,下面是我的解释
在给定格式说明符%s的情况下,给定参数被标识/解释为字符串(char*)的基址。现在char*和int在逻辑上是相等的(忽略符号和C使用的其他属性)
所以在一个非常原始的层面上
printf("%s", k);
可能看起来像这样
int a = "String" ;
%s格式说明符的参数将被视为(char*)
现在,在%s作为格式说明符的情况下,程序应该从给定的地址开始扫描内存的每个字节,并将其类型转换为char,然后打印(当然,取决于可打印值与否,结果可能会很复杂)
可怕的)
在我们的例子中,虽然将a的给定值反引用到char*不会产生任何问题,因此没有错误,但是这并不一定总是这样。由于各种原因。您的代码忽略了C的类型系统,因此在试图理解代码时需要忽略类型系统 我希望您的计算机上的sizeof(int)==sizeof(char*)。常量char*文本被分配给k。这是因为机器上的每个字节都有一个整数地址。类型系统的“引擎盖下”,指针就是这个整数 printf之所以能够工作,是因为它将k解释为以null结尾的数组的const char*,这是您分配给k的
正如其他人指出的,您的代码不能保证工作,因此它不应该出现在您计划发布的任何软件中。我知道这没有意义,但为什么它会工作?什么工作?UB意味着任何事情都可能是结果。别再做那种蠢事了。您通常会得到意外的结果。这就是为什么在编译~1对未定义行为的法律响应是按照程序员的意图执行时,您应该使用
-Werror
标志的原因。然而,你不能指望它。上面的代码在ILP32型号上或像68k这样有单独地址和整数寄存器的CPU上不起作用。实际上,这会发出警告初始化使指针变成整数。
这段代码是如何为您编译的???@thunderwilling代码编译时不会出错(假设没有-Werror
标志),只有警告,我不知道怎么做。它是在CodeBlocks和Visual Studio 2013上编译的。对,我使用的是-weror。代码很可能不会在64位平台上运行,因为当该地址存储在k
中时,k
的地址的32位上限丢失,因为k
只有32位宽。“因为两者大小相同”64位实现通常不会出现这种情况。
printf("%s", k);
int a = "String" ;
a contains Base address of String ( this is some read only location )
+-----+-----+-----+-----+
| 0x123456 |
+-----+-----+-----+-----+
And String may be defines as below with 'S' at location 0x123456
0x123456
+-----+-----+-----+-----+-----+-----+-----+
| S | t | r | i | n | g | \0 |
+-----+-----+-----+-----+-----+-----+-----+