#include <stdio.h>
int main()
{
int a = "Hi";
char b = 'F';
int c = a + b;
printf("%d",a); /* (1) */
printf("%d",c); /* (2) */
}
指令(1)的输出为何为18537? 如何按照ANSI标准存储值
说明(2)很清楚,因为我们基本上在18537上加了70,即为18607
可以用字符串来详细说明如何将值存储在整数变量中吗?
答案 0 :(得分:6)
编译器警告!
$ cc -Wall -Wextra e.c
e.c: In function ‘main’:
e.c:4:13: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
int a = "Hi";
^~~~
您将字符串文字的内存地址分配给变量a
。好吧,在许多情况下,您都可以这样做。但是,这不能保证并且存在潜在的问题。例如,int
可能不足以容纳整个地址。
可能值得指出的是,这不是有效的C代码,因此请不要这样做。根据{{3}}(感谢@Lundin提供链接):
应满足以下条件之一:112)
- 左操作数具有原子,合格或不合格的算术类型,而右操作数具有算术类型;
- 左操作数具有与右类型兼容的结构或联合类型的原子,合格或不合格版本;
- 左操作数具有原子,合格或不合格的指针类型,并且(考虑到左操作数在左值转换后将具有的类型),两个操作数都是指向兼容类型的合格或不合格版本的指针,并且由左侧具有右侧所指类型的所有限定词;
- 左操作数具有原子,合格或不合格的指针类型,并且(考虑到左操作数在左值转换后将具有的类型),一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的void,并且左侧指向的类型具有右侧指向的类型的所有限定符;
- 左操作数是原子,限定或不限定的指针,右是空指针常量;或
- 左操作数的类型为atomic,qualified或unqualified _Bool,而右侧是指针。
有关如何强制编译器不接受无效代码的信息,请参见https://port70.net/~nsz/c/c11/n1570.html#6.5.16.1p1。
答案 1 :(得分:5)
int a = "Hi";
不是有效的C代码,并且推测在非标准编译器上可能会执行的操作不是很有意义。
该代码违反了简单分配规则6.5.16.1的约束。没有强制转换,您不能将char*
隐式地分配给int
。
(如果您想阻止无效的C代码在gcc编译器上进行编译,请使用-std=c11 -pedantic-errors
。)
答案 2 :(得分:1)
发生的事很奇怪:
int a = "Hi" // you allocate 4 bytes and put in the chars ('H' [0x48], 'i'[0x69], '\0' [0x0], 1_byte_of_rubbish) so is OK
//a = 0x 00 00 48 69
请注意,第一位被解释为int上的“信号”。 还请记住,内存中的值应为0X [rubbish] 004869
char b= 'F' //you allocate 1 byte and give value F [0x46] (unsigned)
// b=0x46
printf("%d",a) // print what is inside variable a (as SIGNED integer)
int c = a + b // you add a (signed) and b (unsigned) and put result in c (signed) -> 0x[00]004869 + 46 = 0x000048AF
//c=0x000048AF
printf("%d",c) // you print the content of c interpreted as signed int
请注意,大多数编译器会将变量初始化为0,因此您会得到00 [004869],如果编译器不这样做,则会由于无法初始化int的第一个字节而导致无法预测的结果
还请记住字节序->首先使用LSB读取intel(小字节序)计算机上的int,因此打印%d将为您提供错误的值(在您的情况下,[48] [69] [00] [00] = 26952读为小尾数法
编辑: 我的建议是始终“十六进制”调试这些情况,以便您可以确切地看到每个字节中的内容,有时(涉及排序的时候)分贝数很少。