C语言,变量与内存
一、数在计算机中的二进制表示
符号位:最高位为符号位,正数该位为0,负数该位为1;
原码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值
反码:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
补码: 正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)。
正数的原码、补码、反码表示方法均相同,不需转换。
任何数值在内存中都是以补码的形式存储的。
- 正数的补码与原码相同。比如9的原码和补码都是1001。
- 负数的补码等于它正数的原码按位取反后再+1。
负数补码计算:
1> -10的二进制形式 :1000 0000 0000 0000 0000 0000 0000 1010 //原
2> 除符号位取反 :1111 1111 1111 1111 1111 1111 1111 0101 //反
3> 对取反后的结果+1 :1111 1111 1111 1111 1111 1111 1111 0110 //补
二、基本数据类型
in linux-32:
sizeof(char) = 1
sizeof(int) = 4
sizeof(short int) = 2
sizeof(long int) = 4
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 12
三、综合示例,说明变量的二进制表示以及在内存中的分布:
#include "stdafx.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include "t.h" void f0(void); typedef struct ds{ unsigned int ui; int i; int j; long int li; char c; unsigned char uc; short int si; unsigned short int usi; float f; double d; long double ld; char data[]; }DST; int t1(void) { f0(); DST* pdst = (DST*)malloc(sizeof(DST)+1000); if(pdst == 0){ return -1; } memset(pdst, 0, sizeof(DST)+1000); pdst->ui = 0xffffffff; pdst->i = pdst->ui; pdst->j = -2147483648; pdst->li = -2147483648; pdst->c = -1; pdst->uc = -1; pdst->si = -1; pdst->usi = -1; pdst->f = -1; pdst->d = -1; pdst->ld = -1; printf("pdst->c addr = %08x\n", &(pdst->c) ); printf("pdst->uc addr = %08x\n", &(pdst->uc) ); printf("pdst->si addr = %08x\n", &(pdst->si) ); printf("pdst->usi addr = %08x\n", &(pdst->usi) ); printf("pdst->f addr = %08x\n", &(pdst->f) ); printf("pdst->d addr = %08x\n", &(pdst->d) ); printf("pdst->ld addr = %08x\n", &(pdst->ld) ); free(pdst); pdst = 0; return 0; } void f0(void) { printf("in vs2010:\n"); printf("sizeof(char) = %d\n", sizeof(char)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(short int) = %d\n", sizeof(short int)); printf("sizeof(long int) = %d\n", sizeof(long int)); printf("sizeof(float) = %d\n", sizeof(float)); printf("sizeof(double) = %d\n", sizeof(double)); printf("sizeof(long double) = %d\n", sizeof(long double)); }
内存中的i是0xffffffff,
(1)转化为二进制 1111 1111 1111 1111 1111 1111 1111 1111
(2)发现是负数
(3)减一 1111 1111 1111 1111 1111 1111 1111 1110
(4)除符号位取反 1000 0000 0000 0000 0000 0000 0000 0001 ; 真值为-1
内存中的j是0x80000000,(最小的一个负值,暂时还不能理解,因为借了一位才能完成这换算,需33位,不知是不是因为cpu中的计算单元有33位以上寄存器。)
(1)转化为2进制, 1000 0000 0000 0000 0000 0000 0000 0000
(2)发现是负数
(3)减一 1 0111 1111 1111 1111 1111 1111 1111 1111
(4)除符号位取反1 1000 0000 0000 0000 0000 0000 0000 0000 ;真值为-231= -2147483648