int main()
{
int i;
char a[100];
for(i=0; i<100; i++)
a[i] = -1 - i;
printf(“%d\n”, strlen(a));
}
在计算机系统中, 数值采用补码来表示(存储),正数的补码和原码一致,负数的补码:符号位为1,其余位为该数的绝对值的原码按位取反,然后整个数加1.
-1的补码是0xff,-2的补码是0xfe,当i的值为127时,a[127]=-128,char最小能表示-128,当i增加时,会发生溢出。char类型数据只有8位, -129需要9位才能存储,所以最高位被丢弃剩下的8位是原来补码的低8位,即0x7f。当i继续增加到255时,-256的补码的低8位是0。然后当i增加到256时,-257的补码的低8位为0xff,此时能重新存储。
所以结果为255。
编译器通常不为普通const变量分配存储空间,而是将他们保存在符号表中, 这使得它成为一个编译期间的值,没有了存储于度内存的操作,使得它的效率也很高。
eg:
#define m 3 //宏常量
const int n 5 //此时并未将n放入内存中
……
int i = n; // 此时为n分配内存,以后不再分配
int i = m; // 预编译期间进行宏替换,分配内存
int j = n; //没有内存分配
int j = m; // 再进行宏替换,再次分配内存
const定义的只读变量从汇编 的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的只读变量在程序运行过程中只有一份拷贝(因为此处是全局的只读变量,存放在静态区),而#define定义的宏替换在内存中有若干拷贝。#define宏是在预编译阶段进行替换,而const修饰的只读变量时在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。
const的修饰对象:
近水楼台先得月:离谁近就修饰谁
判断的时候先忽略类型名:
const (int) *p //修饰*p,指针可变,指向的对象不可变
(int) const *p //同上
(int)*const p // 修饰p,指针不可变,指向的对象可变
空结构的大小为1
union:一个union只配置一个足够大的空间以容纳最大长度的数据成员,也就是说union里的成员同一时间不可能同时存在
大端模式:字数据的高字节存储在低地址中,而字数据的低字节存储在高地址中;
小端模式:字数据的高字节存储在高地址中,而字数据的低字节存储在低地址中;
使用函数确定系统的存储字节序
int i = 1;
小端模式:
0x0
0x1
高地址 低地址
大端模式:
低地址 高地址
数据读取从高地址开始读取;
code:
int checksysytem()
union check{
int i;
char ch;
}c;
c.i = 1;
return (1 == c.ch);
如果系统是大端存储,则函数中c.ch=0, 如果系统是小端存储,则函数中c.ch=1;
enum 枚举
常量的集合 未赋值则自动赋值为上一个常量+1