常量与变量 运算符和表达式
2016-02-19 15:59
225 查看
++++++++++++++++++++++++++++++++++++++++++
《C语言深入理解系列 - 常量与变量》
查看其它博文请关注原创作者。
本文系本站原创,欢迎转载! 转载请注明出处:
/article/1433060.html
++++++++++++++++++++++++++++++++++++++++++
常量与变量
正所谓静中有动,动中有静,常量与变量亦是如此,它们之前相互依赖,相互影响。关于常量与变量,很多朋友可能觉得没有什么好介绍的,它实在是太简单了,单从字面上看就知道什么意思?我想说的不是关于常量与变量的概念,而是其深入的实质。
其实很多朋友在学到后面指针的时候经常会出现,段错误,晕指针(我对那些指针恐惧者的症状叫法),野指针等问题,都是因为对常量和变量的理解不够深入,基础理解不够踏实。
常量:其值不会发生改变的量,称为常量。它们可以和数据类型接合起来分类。比如:整形常量,浮点型常量,字符常量等等,常量是可以不经过定义和初始化,而直接引用的。
常量分类:常量又分为:直接常量和符号常量。
直接常量又叫做:字面常量。如12,0,4.6,’a’,”abcd”
符号常量:如宏定义的:#define PI 3.14
特点:常量的值在其作用域内不会发生改变,也不能再被赋值。其在出现时就被当作一个立即数来使用。也就是说,只能被访问,被读,而不能被写,被赋值。
其实,你一旦声明了一个常量,那么常量所在的内存空间就被加上了只读的属性,它有点类似于const关键字。
变量:其值在其作用域内可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储空间。变量在使用前必须要定义。每个变量都有自己的地址。
变量分类:变量依据其定义的类型,分为不同类型,如:整型变量,字符型变量,浮点型变量,指针型变量等等。
特点:变量其值可以发生改变,意味着它可以被覆盖,被写入,被赋值。每个变量必须要有一个名字和它所在内存空间绑定,如图xxx所示。
图xxx 变量内存空间示意图
代码中声明整型变量a,它的类型已经决定,那么它的大小也就是4个字节(32位机上),那么在内存中就有连续的四个字节与之对应,a变量名就代表了这四个字节的空间,a变量的地址就是连续四个字节的开始的地址0x000。就好像是饭店里每个房间都有一个地址,如201室代表二楼每一个房间,叫201不太雅观,我们起个名字叫:牡丹厅。那么,我们人为的将“牡丹厅”这个名字和201房间绑定在了一起。当我们说到牡丹厅,就知道是201房间,同样当我们说201房间我们也知道是牡丹厅。
同样的道理,当我们说a变量,就知道是从0x000这个地址开始的4个字节,当我们说0x000地址就知道这是a变量的空间。那么既然a是变量也就是说它所代表的空间里的数据是可以修改的,同样0x000地址处的数据也是可以修改的。
变量名和变量的值:
变量名是在变量的声明的时候,该名字就和内存中一块地址绑定在一起了。可以通过变量名直接找到对应的内存区域,也可以通过地址找到其内存区域。
变量的值是变量所对应的内存区域内存放的二进制序列。变量的值不会因为变量的类型发生了改变而改变,当变量被转换为对应类型时,内存区域的二进制序列以该类型的形式翻译出来。这也是强制类型转换能够成立的原因。
例如:
[cpp] view
plain copy
int a = 97;
char ch1 = ‘a’;
char ch2 = (char)a;
char *p = (char*)a;
第一行代码:整型变量a在内存中是以97的二进制形式存放的,当使用它时,会被以十进制形式表现出来。
第二行代码:字符变量ch1的ASCII 码是97,也是以97的二进制存放的,使用时,会被以字符’a’的形式表现出来。
第三行代码:将整型变量a强制类型转换成字符型,a变量里的值没有变,变的是它的类型,它里面的值还是97的二进制,它类型变成了char,97的二进制变成char型,表现出来就是字符’a’。
第四行代码:声明一个字符型指针变量p,p是个变量,它里面的值可变,它的值是整型变量a的值强制类型转换成了字符指针类型。这个时候p里的值还是97的二进制,只不过这个97的意义已经代表了一个字符型指针,也就是一个指向字符的地址了。
由此可见:变量在内存中存放和它的值没有关系,而是和它的类型相关的。同样我们也可以得出:一个二进制序列对于计算机本身而言没有任何意义,计算机根本不知道这个二进制数据是干什么的,只有具体到它的类型时或出现在合适的场合时,才能代表具体的意义。如果一串二进制数据出现在地址总线上,它代表是一个地址,如果该相同数据出现在数据总线上,它代表是一个数据。所以,当我们看到一个数据时,比如:3.1415926,不能把它戴上定向思维的帽子认为它就是PI,而是要看清它的本质,它就是一堆二进制代码。
我们来看下下面的例子:
1.
char ch = ‘a’;
int a = (int)ch;
printf(“%d %c\n”, a, ch);
ch是什么?ch里装的是什么?a是什么?a里面装的是什么?打印什么?
2.
int add = 0x12345678;
int *p = (int*)add;
add是什么?add里装的是什么?p是什么?p里装的是什么?*p又是什么?&p又是什么?
3.
#define PI 3.14
int a = PI;
printf(“%d\n”, a);
上面的代码有没有问题?
4.
#define PI 3.14
printf(“%d\n”, PI);
代码有没有问题?
5.
#define PI 3.14
int a = PI;
PI = 3.1415926;
int b = PI;
printf(“%d %d\n”, a, b);
代码有没有问题?
6.
char *str = “hello world”;
printf(“%s\n”, str);
*str = “goodbye world”;
printf(“%s\n”, str);
代码有没有问题?
答案:
1. 测试对变量类型的理解和类型转换。ch是字符型变量,ch里是字符’a’的二进制数,a是整型变量,a里面是字符’a’的二进制数的整型表示方式,以十进制数表示出来97。打印结果为97 和 a。
2. 测试对整型和地址类型转换。add是一个整数变量,add里是0x12345678的二进制数,以十进制表现出来,p是一个整型指针变量名,p里面是0x12345678的二进制数,以地址的方式表现出来,代表地址0x12345678。*p是通过*去访问地址0x12345678这个地址处的数据(如果你试图去打印它,会出错,因为这个地址你不一定有权限去访问)。&p是取出整型指针变量p的地址,因为p是一个变量,它也有自己的地址,所以可以取出它的地址来(见上面变量的定义)。
3. 宏定义一个常量PI,PI这个符号代表了3.14,在代码执行前的预处理阶段第二行int a = PI,已经被替换为了int a = 3.14,将3.14赋值给整型,会舍弃掉小数点后面部分结果,仅保留整数部分,打印结果为3。
4. 和上面3一样,在预处理阶段被替换成了printf(“%d\n”, 3.14),结果为1374389535,这是因为将浮点型的3.14在内存中的数据,以整型来表现的。
5. 第三行PI = 3.1415926会出错,PI是个常量其被替换成了3.14 = 3.1415926,3.14是个字面常量,不能被赋值。错误信息为“向无效左值赋值出错”(关于常见错误信息,见C语言常见错误详解章节)。
6. 第三行*str = “goodbye world”出错,第一行中将字符串常量“hello world”的首地址给了字符指针变量str,第三行试图将“goodbye world”的首地址,通过*str的访问方式覆盖str指向的字符串常量“hello world”。这句话理解起来都比较费劲,因为这里有两个错误:
试图向常量里写数据。
“hello world” 是字符串常量,那么这个字符串空间里的内容不能改变。
指针变量里应该放地址,字符串都是以首地址为地址。
向一个地址里写入字符串应该使用strcpy。*str只是代表了str指向的字符串中的第一个字符,将字符串地址写入到一个字符里肯定不行。
C运算符优先级完整口诀
C语言常用运算符的优先级口诀是:“单算关逻条赋逗”;
如果加入位运算符,完整口诀是:“单算移关与,异或逻条赋”。
■“单”表示单目运算符:逻辑非(!),按位取反(~),自增(++),自减(--),取地址(&),取值(*);
■“算”表示算术运算符:乘、除和求余(*,/,%)级别高于加减(+,-);
■“移”表示按位左移(<<)和位右移(>>);
■“关”表示关系运算符:大小关系(>,>=,<,<=)级别高于相等不相等关系(==,!=);
■“与”表示按位与(&);
■“异”表示按位异或(^);
■“或”表示按位或(|);
■“逻”表示逻辑运算符:逻辑与(&&)级别高于逻辑或(||);
■“条”表示条件运算符(? :);
■“赋”表示赋值运算符(=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=, |=,!=);
◆另,逗号运算符(,) 级别最低,口诀中没有表述,需另加记忆...
#include <stdio.h>
//常量:常量是计算机中最基本的元素,如:整型常量,浮点类型常量,字符常量,字符串常量,枚举常量...
//字符常量: 'a' '/'
//ASCII码(美国信息交换码):
//'0' 48
//'A' 65
//'a' 97
//转义字符: '\n' '\0' '\t' '\\' '\'' '\"'
//字符常量用单引号括起来
//字符常量在内存中占用4字节空间
//
//字符串常量: "qianfeng" "hello world"
//1.用双引号包含
//2.末尾以'\0'结束
//3.字符串中的每一个元素占用一个字节
//
//'a' "a"
//1. 'a'占用4字节空间
//2. "a"占用两个字节空间
//3. 一个单引号一个双引号
//'0' 0 '\0' "0"
#include <stdio.h>
//
//int main(int argc, const char * argv[])
//{
// printf("%c\n",'a');//%c打印字符
// printf("%ld\n",sizeof('a'));
// printf("%ld\n",sizeof("qianfeng"));
// printf("%c\n",'\\');
// printf("%c\n",'\'');
// printf("%%%c\n",'%');
//
// printf("%s\n","hello\0world");//%s打印字符串占位符
//
// printf("qinafeng\n");
//
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// //整型常量
// //%d %ld %u %lu
// printf("%d %d %d\n",'a',345, 56789);//%d
对应 char short int
// printf("%ld\n",4567890456789567);//%ld
对应 long long long
// printf("%lu\n",5678956789456789089);//%lu unsigned long long long
//
// //%f %lf %Lf (精度不同)
// printf("%f\n",3.5678956789);
// printf("%.15lf\n",7.2345678903456789);
// long double f=4567.345678904563456789078;
// printf("%Lf\n",f);
// return 0;
//}
//变量:变量一段命名的内存空间
//int a; 4字节
//数据类型 +标示符
//标示符:以字母或者下划线开头,后面跟一个或者多个字母数字下划线;
// abc _yui123 ___ union int 123cbd
//1. 必须以字母或者下划线开头
//2. 后面必须跟数字字母下划线
//3. 不能跟C语言中的关键字重复
//4. 下划线开头的标示符通常给编译器使用
//变量在内存空间中占用大小,取决于其数据类型
//int a; char ch; float f1;
//long l1;
//初始化:在定义的变量的时候,给一个初值;
//int main(int argc, const char *argv[])
//{
// //char ch = 'a';
// char ch=0;
// ch= 'a';
// printf("%ld %ld\n",sizeof(ch),sizeof('a'));
//
// return 0;
//}
//变量声明:声明一个变量,就是告诉编译器有这个变量的存在
//变量定义是声明的一种,是一种特殊的声明
//extern int a;//变量的声明
//
//int main(int argc, const char *argv[])
//{
// //printf("%d",a);
// char ch='a';
//
// char ch2 = ch;
// printf("%c\n",ch2);
// return 0;
//}
//
//int a=20;
//运算符
//强制转换: (数据类型)表达式
//自增自减运算符: ++ --
//sizeof运算符:求变量或者常量占用内存空间大小
//算术运算符: / * % + -
//关系运算符: > >= < <= == !=
//逻辑运算符: ! && ||
//条件运算符: ? :
//赋值运算符: = /= *= %= += -=
//逗号运算符: ,
//表达式:由常量变量运算符组成一个式子;
//12+45 a+b 3*a (a+b)*3
//表达式有确定的类型跟数值;
//int main(int argc, const char * argv[])
//{
// printf("%d\n",12+45);
//
// return 0;
//}
//自增自减运算符: ++ --
//int main(int argc, const char *argv[])
//{
// int a=10;
// int b=20;
// printf("a= %d b= %d\n", a++,b--);//a++ b--
在当前语句执行之后++ -- a++ <==> a+=1 <==> a=a+1; b-- <==> b-=1 <==> b=b-1;
//
// printf("a= %d b = %d\n", a,b);
//
// a = 10;
// b= 20;
//
// printf("a = %d b= %d\n" ,++a,--b);//先变化a,b的值
// printf("a = %d b= %d\n" ,a,b);
// //printf("%d", ++a++);错误
// //printf("%d %d\n",a++,a--);//a的值是未定义的
// return 0;
//}
//算术运算符: / * % + -
//
//int main(int argc, const char *argv[])
//{
// int a=10,b=20;
// int c=0;
// printf("a+b = %d\n", c=a+b);
// printf("a*b = %d\n", a*b);
// printf("a-b = %d\n", a-b);
// printf("a/b = %d\n", a/b);
// printf("a%%b = %d\n", a%b);//取模
//
// printf("%d\n", a-b*a);
// return 0;
//}
//关系运算符: > >= < <= == !=
//表达式成立
则为真(!0), 否则为假(0)
//int main(int argc, const char *argv[])
//{
// int a= 10, b=20;
//
// printf("%d\n",a>b);
// printf("%d\n",a<b);
// printf("a<=b %d\n",a<=b);
// printf("a>=b %d\n",a>=b);
// printf("a==b %d\n",a==b);
// printf("a!=b %d\n",a!=b);
//
// return 0;
//}
//逻辑运算符: ! && ||
//! (逻辑非)
// 表达式 !(表达式)
// 真(!0) 假(0)
// 假(0) 真(!0)
//int main(int argc, const char *argv[])
//{
// int a=0;
// printf("!a = %d\n",!a);
//
//
// return 0;
//}
//&&(逻辑与)
//表达式1
表达式2 表达式
// 真
真 真
// 假
真 假
// 真
假 假
// 假
假 假
//当有一个表达式不成立,那么整个表达式不成立
//int main(int argc, const char *argv[])
//{
// int a = 0,b=20;
//
// printf("a&&b = %d\n",a&&b);
//
// return 0;
//}
//||逻辑或
// 表达式1
表达式2 ... 表达式
// 真
真 真
// 假
真 真
// 真
假 真
// 假
假 假
//当有一个表达式为真,则整个表达式为真
//int main(int argc, const char *argv[])
//{
// int a=0,b=0;
//
// printf("a||b = %d\n", a||b);
//
// return 0;
//}
//条件运算符: ? :
//三目运算符
//表达式?表达式1:表达式2
//先判断表达式是否成立,成立整个表达式的值就是表达式1的值,反之是表达式2的值
//int main(int argc, const char *argv[])
//{
// int a= 30, b = 20;
// printf("max(a,b) = %d\n", a>b?a:b);
// printf("min(a,b) = %d\n", a>b?b:a);
// return 0;
//}
//赋值运算符: = /= *= %= += -=
//int main(int argc, const char *argv[])
//{
// int a=40;
// int b=4;
// //b = 50;
// printf("a= %d\n",a/=2);//a = a/2;
// a = 40;
// printf("a*=b = %d\n",a*=b);//a=a*b;
// a = 40;
// printf("a/=b = %d\n",a/=b);//a=a/b;
// a =40;
// printf("a%%=b = %d\n",a%=b);//a=a%b;
//
// a =40;
// printf("a+=b = %d\n", a+=b);//a= a+b;
//
// a= 40;
// printf("a-=b = %d\n", a-=b);//a=a-b;
// //printf("%d %d\n", a+=b,a-=b);//a的值未定义
// return 0;
//}
//逗号运算符: ,
//表达式1,表达式2,表达式3,表达式4,.....表达式n
//逗号表达式的值是表达式n的值
//int main(int argc, const char *argv[])
//{
// int a=10,b=20,c=30,d=40;
// //int f = 0;
// int e;
//// e=a+b,c+d;
// printf("%d\n",(e=a+b,c+d));
// printf("%d\n",(e=c+d,a+b));
//
// return 0;
//}
//运算符优先级
//括号 >
单目运算符 > 算术运算符(/ * % > + -) >关系运算符 >逻辑运算符 (&& > ||)
>三目运算符 >
赋值运算符 >逗号运算符
//采用加括号的方式提高优先级
//类型转换
//
//int a=5 + char b=6
// 0000 0000 0000 0000 0000 0000 0000 0101
// + 0000 0000 0000 0000 0000 0000 0000 0110 //位扩展
//-----------------------------------------------
// 0000 0000 0000 0000 0000 0000 0000 1011 = 11
// int a=5 char b=-6
// 0000 0000 0000 0000 0000 0000 0000 0101
// 1111 1111 1111 1111 1111 1111 1111 1010 //补1
//--------------------------------------------
// 1111 1111 1111 1111 1111 1111 1111 1111 = -1
//int main(int argc, const char *argv[])
//{
// int a=5;
// char b = 6;
// printf("%d\n",a+b);//
位扩展 发生隐式转换
//
//
// int c= 0x123350; //位截断
// short d;
// d = c;
//
// printf("d=0x%x\n",d);
// return 0;
//}
//1.整型数据之间运算,
当有long long 其它类型的数据向long long看齐
//2.没有 long long有long类型其它类型向long类型看齐
//3.既没有long long也没有long 有int类型数据,其它类型数据向int类型数据看齐
//4. 只有char short类型向 int类型数据看齐
//5. 有浮点类型数据的时候,向浮点类型数据看齐(整型转浮点类型)
//6. float double 向 long double看齐
//7. 没有long double有double向double看齐
//8. 有符号类型向无符号类型数据看齐
//int main(int argc, const char *argv[])
//{
// int a=10;
// float f=3.45;
//
// printf("%f\n",a+f);//隐式转换
// printf("%d\n",(int)(a+f));//强制转化
// return 0;
//}
//0000 0000 0000 0000 0000 0000 0000 0101
//1111 1111 1111 1111 1111 1111 1111 1010
//------------------------------------------
//
//int main(int argc,const char *argv[])
//{
// unsigned int a = 5;
// char b = -6;
//
// printf("%d\n",a+b);
//
// return 0;
//}
//control + i //排序代码
//int main(int argc, const char *argv[])
//{
// char a;
// int b = 0x56756;
// a = b;//截断
// printf("%d %ld\n",a,sizeof(a));
//
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// int a = 256;//0000 0000 0000 0000 00000 10000 0000
// char b;
// b = a;
// printf("%d\n",b);
// return 0;
//}
//511 /16 15
//31 /16 15
//1 /16 1
////0x1ff
//int main(int argc,const char *argv[])
//{
// int a = 511;
// char b;
// b = a; //1111 1111
// printf("%d\n",b);
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// int a;
// float b = 3.14;
// a = b;
// printf("%d\n",a);
// return 0;
//}
int main(int argc,constchar *argv[])
{
float a =3.14;
int b;
b = (int)a%2;
printf("%d\n",b);
return 0;
}
《C语言深入理解系列 - 常量与变量》
查看其它博文请关注原创作者。
本文系本站原创,欢迎转载! 转载请注明出处:
/article/1433060.html
++++++++++++++++++++++++++++++++++++++++++
常量与变量
正所谓静中有动,动中有静,常量与变量亦是如此,它们之前相互依赖,相互影响。关于常量与变量,很多朋友可能觉得没有什么好介绍的,它实在是太简单了,单从字面上看就知道什么意思?我想说的不是关于常量与变量的概念,而是其深入的实质。
其实很多朋友在学到后面指针的时候经常会出现,段错误,晕指针(我对那些指针恐惧者的症状叫法),野指针等问题,都是因为对常量和变量的理解不够深入,基础理解不够踏实。
常量:其值不会发生改变的量,称为常量。它们可以和数据类型接合起来分类。比如:整形常量,浮点型常量,字符常量等等,常量是可以不经过定义和初始化,而直接引用的。
常量分类:常量又分为:直接常量和符号常量。
直接常量又叫做:字面常量。如12,0,4.6,’a’,”abcd”
符号常量:如宏定义的:#define PI 3.14
特点:常量的值在其作用域内不会发生改变,也不能再被赋值。其在出现时就被当作一个立即数来使用。也就是说,只能被访问,被读,而不能被写,被赋值。
其实,你一旦声明了一个常量,那么常量所在的内存空间就被加上了只读的属性,它有点类似于const关键字。
变量:其值在其作用域内可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储空间。变量在使用前必须要定义。每个变量都有自己的地址。
变量分类:变量依据其定义的类型,分为不同类型,如:整型变量,字符型变量,浮点型变量,指针型变量等等。
特点:变量其值可以发生改变,意味着它可以被覆盖,被写入,被赋值。每个变量必须要有一个名字和它所在内存空间绑定,如图xxx所示。
图xxx 变量内存空间示意图
代码中声明整型变量a,它的类型已经决定,那么它的大小也就是4个字节(32位机上),那么在内存中就有连续的四个字节与之对应,a变量名就代表了这四个字节的空间,a变量的地址就是连续四个字节的开始的地址0x000。就好像是饭店里每个房间都有一个地址,如201室代表二楼每一个房间,叫201不太雅观,我们起个名字叫:牡丹厅。那么,我们人为的将“牡丹厅”这个名字和201房间绑定在了一起。当我们说到牡丹厅,就知道是201房间,同样当我们说201房间我们也知道是牡丹厅。
同样的道理,当我们说a变量,就知道是从0x000这个地址开始的4个字节,当我们说0x000地址就知道这是a变量的空间。那么既然a是变量也就是说它所代表的空间里的数据是可以修改的,同样0x000地址处的数据也是可以修改的。
变量名和变量的值:
变量名是在变量的声明的时候,该名字就和内存中一块地址绑定在一起了。可以通过变量名直接找到对应的内存区域,也可以通过地址找到其内存区域。
变量的值是变量所对应的内存区域内存放的二进制序列。变量的值不会因为变量的类型发生了改变而改变,当变量被转换为对应类型时,内存区域的二进制序列以该类型的形式翻译出来。这也是强制类型转换能够成立的原因。
例如:
[cpp] view
plain copy
int a = 97;
char ch1 = ‘a’;
char ch2 = (char)a;
char *p = (char*)a;
第一行代码:整型变量a在内存中是以97的二进制形式存放的,当使用它时,会被以十进制形式表现出来。
第二行代码:字符变量ch1的ASCII 码是97,也是以97的二进制存放的,使用时,会被以字符’a’的形式表现出来。
第三行代码:将整型变量a强制类型转换成字符型,a变量里的值没有变,变的是它的类型,它里面的值还是97的二进制,它类型变成了char,97的二进制变成char型,表现出来就是字符’a’。
第四行代码:声明一个字符型指针变量p,p是个变量,它里面的值可变,它的值是整型变量a的值强制类型转换成了字符指针类型。这个时候p里的值还是97的二进制,只不过这个97的意义已经代表了一个字符型指针,也就是一个指向字符的地址了。
由此可见:变量在内存中存放和它的值没有关系,而是和它的类型相关的。同样我们也可以得出:一个二进制序列对于计算机本身而言没有任何意义,计算机根本不知道这个二进制数据是干什么的,只有具体到它的类型时或出现在合适的场合时,才能代表具体的意义。如果一串二进制数据出现在地址总线上,它代表是一个地址,如果该相同数据出现在数据总线上,它代表是一个数据。所以,当我们看到一个数据时,比如:3.1415926,不能把它戴上定向思维的帽子认为它就是PI,而是要看清它的本质,它就是一堆二进制代码。
我们来看下下面的例子:
1.
char ch = ‘a’;
int a = (int)ch;
printf(“%d %c\n”, a, ch);
ch是什么?ch里装的是什么?a是什么?a里面装的是什么?打印什么?
2.
int add = 0x12345678;
int *p = (int*)add;
add是什么?add里装的是什么?p是什么?p里装的是什么?*p又是什么?&p又是什么?
3.
#define PI 3.14
int a = PI;
printf(“%d\n”, a);
上面的代码有没有问题?
4.
#define PI 3.14
printf(“%d\n”, PI);
代码有没有问题?
5.
#define PI 3.14
int a = PI;
PI = 3.1415926;
int b = PI;
printf(“%d %d\n”, a, b);
代码有没有问题?
6.
char *str = “hello world”;
printf(“%s\n”, str);
*str = “goodbye world”;
printf(“%s\n”, str);
代码有没有问题?
答案:
1. 测试对变量类型的理解和类型转换。ch是字符型变量,ch里是字符’a’的二进制数,a是整型变量,a里面是字符’a’的二进制数的整型表示方式,以十进制数表示出来97。打印结果为97 和 a。
2. 测试对整型和地址类型转换。add是一个整数变量,add里是0x12345678的二进制数,以十进制表现出来,p是一个整型指针变量名,p里面是0x12345678的二进制数,以地址的方式表现出来,代表地址0x12345678。*p是通过*去访问地址0x12345678这个地址处的数据(如果你试图去打印它,会出错,因为这个地址你不一定有权限去访问)。&p是取出整型指针变量p的地址,因为p是一个变量,它也有自己的地址,所以可以取出它的地址来(见上面变量的定义)。
3. 宏定义一个常量PI,PI这个符号代表了3.14,在代码执行前的预处理阶段第二行int a = PI,已经被替换为了int a = 3.14,将3.14赋值给整型,会舍弃掉小数点后面部分结果,仅保留整数部分,打印结果为3。
4. 和上面3一样,在预处理阶段被替换成了printf(“%d\n”, 3.14),结果为1374389535,这是因为将浮点型的3.14在内存中的数据,以整型来表现的。
5. 第三行PI = 3.1415926会出错,PI是个常量其被替换成了3.14 = 3.1415926,3.14是个字面常量,不能被赋值。错误信息为“向无效左值赋值出错”(关于常见错误信息,见C语言常见错误详解章节)。
6. 第三行*str = “goodbye world”出错,第一行中将字符串常量“hello world”的首地址给了字符指针变量str,第三行试图将“goodbye world”的首地址,通过*str的访问方式覆盖str指向的字符串常量“hello world”。这句话理解起来都比较费劲,因为这里有两个错误:
试图向常量里写数据。
“hello world” 是字符串常量,那么这个字符串空间里的内容不能改变。
指针变量里应该放地址,字符串都是以首地址为地址。
向一个地址里写入字符串应该使用strcpy。*str只是代表了str指向的字符串中的第一个字符,将字符串地址写入到一个字符里肯定不行。
C运算符优先级完整口诀
C语言常用运算符的优先级口诀是:“单算关逻条赋逗”;
如果加入位运算符,完整口诀是:“单算移关与,异或逻条赋”。
■“单”表示单目运算符:逻辑非(!),按位取反(~),自增(++),自减(--),取地址(&),取值(*);
■“算”表示算术运算符:乘、除和求余(*,/,%)级别高于加减(+,-);
■“移”表示按位左移(<<)和位右移(>>);
■“关”表示关系运算符:大小关系(>,>=,<,<=)级别高于相等不相等关系(==,!=);
■“与”表示按位与(&);
■“异”表示按位异或(^);
■“或”表示按位或(|);
■“逻”表示逻辑运算符:逻辑与(&&)级别高于逻辑或(||);
■“条”表示条件运算符(? :);
■“赋”表示赋值运算符(=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=, |=,!=);
◆另,逗号运算符(,) 级别最低,口诀中没有表述,需另加记忆...
#include <stdio.h>
//常量:常量是计算机中最基本的元素,如:整型常量,浮点类型常量,字符常量,字符串常量,枚举常量...
//字符常量: 'a' '/'
//ASCII码(美国信息交换码):
//'0' 48
//'A' 65
//'a' 97
//转义字符: '\n' '\0' '\t' '\\' '\'' '\"'
//字符常量用单引号括起来
//字符常量在内存中占用4字节空间
//
//字符串常量: "qianfeng" "hello world"
//1.用双引号包含
//2.末尾以'\0'结束
//3.字符串中的每一个元素占用一个字节
//
//'a' "a"
//1. 'a'占用4字节空间
//2. "a"占用两个字节空间
//3. 一个单引号一个双引号
//'0' 0 '\0' "0"
#include <stdio.h>
//
//int main(int argc, const char * argv[])
//{
// printf("%c\n",'a');//%c打印字符
// printf("%ld\n",sizeof('a'));
// printf("%ld\n",sizeof("qianfeng"));
// printf("%c\n",'\\');
// printf("%c\n",'\'');
// printf("%%%c\n",'%');
//
// printf("%s\n","hello\0world");//%s打印字符串占位符
//
// printf("qinafeng\n");
//
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// //整型常量
// //%d %ld %u %lu
// printf("%d %d %d\n",'a',345, 56789);//%d
对应 char short int
// printf("%ld\n",4567890456789567);//%ld
对应 long long long
// printf("%lu\n",5678956789456789089);//%lu unsigned long long long
//
// //%f %lf %Lf (精度不同)
// printf("%f\n",3.5678956789);
// printf("%.15lf\n",7.2345678903456789);
// long double f=4567.345678904563456789078;
// printf("%Lf\n",f);
// return 0;
//}
//变量:变量一段命名的内存空间
//int a; 4字节
//数据类型 +标示符
//标示符:以字母或者下划线开头,后面跟一个或者多个字母数字下划线;
// abc _yui123 ___ union int 123cbd
//1. 必须以字母或者下划线开头
//2. 后面必须跟数字字母下划线
//3. 不能跟C语言中的关键字重复
//4. 下划线开头的标示符通常给编译器使用
//变量在内存空间中占用大小,取决于其数据类型
//int a; char ch; float f1;
//long l1;
//初始化:在定义的变量的时候,给一个初值;
//int main(int argc, const char *argv[])
//{
// //char ch = 'a';
// char ch=0;
// ch= 'a';
// printf("%ld %ld\n",sizeof(ch),sizeof('a'));
//
// return 0;
//}
//变量声明:声明一个变量,就是告诉编译器有这个变量的存在
//变量定义是声明的一种,是一种特殊的声明
//extern int a;//变量的声明
//
//int main(int argc, const char *argv[])
//{
// //printf("%d",a);
// char ch='a';
//
// char ch2 = ch;
// printf("%c\n",ch2);
// return 0;
//}
//
//int a=20;
//运算符
//强制转换: (数据类型)表达式
//自增自减运算符: ++ --
//sizeof运算符:求变量或者常量占用内存空间大小
//算术运算符: / * % + -
//关系运算符: > >= < <= == !=
//逻辑运算符: ! && ||
//条件运算符: ? :
//赋值运算符: = /= *= %= += -=
//逗号运算符: ,
//表达式:由常量变量运算符组成一个式子;
//12+45 a+b 3*a (a+b)*3
//表达式有确定的类型跟数值;
//int main(int argc, const char * argv[])
//{
// printf("%d\n",12+45);
//
// return 0;
//}
//自增自减运算符: ++ --
//int main(int argc, const char *argv[])
//{
// int a=10;
// int b=20;
// printf("a= %d b= %d\n", a++,b--);//a++ b--
在当前语句执行之后++ -- a++ <==> a+=1 <==> a=a+1; b-- <==> b-=1 <==> b=b-1;
//
// printf("a= %d b = %d\n", a,b);
//
// a = 10;
// b= 20;
//
// printf("a = %d b= %d\n" ,++a,--b);//先变化a,b的值
// printf("a = %d b= %d\n" ,a,b);
// //printf("%d", ++a++);错误
// //printf("%d %d\n",a++,a--);//a的值是未定义的
// return 0;
//}
//算术运算符: / * % + -
//
//int main(int argc, const char *argv[])
//{
// int a=10,b=20;
// int c=0;
// printf("a+b = %d\n", c=a+b);
// printf("a*b = %d\n", a*b);
// printf("a-b = %d\n", a-b);
// printf("a/b = %d\n", a/b);
// printf("a%%b = %d\n", a%b);//取模
//
// printf("%d\n", a-b*a);
// return 0;
//}
//关系运算符: > >= < <= == !=
//表达式成立
则为真(!0), 否则为假(0)
//int main(int argc, const char *argv[])
//{
// int a= 10, b=20;
//
// printf("%d\n",a>b);
// printf("%d\n",a<b);
// printf("a<=b %d\n",a<=b);
// printf("a>=b %d\n",a>=b);
// printf("a==b %d\n",a==b);
// printf("a!=b %d\n",a!=b);
//
// return 0;
//}
//逻辑运算符: ! && ||
//! (逻辑非)
// 表达式 !(表达式)
// 真(!0) 假(0)
// 假(0) 真(!0)
//int main(int argc, const char *argv[])
//{
// int a=0;
// printf("!a = %d\n",!a);
//
//
// return 0;
//}
//&&(逻辑与)
//表达式1
表达式2 表达式
// 真
真 真
// 假
真 假
// 真
假 假
// 假
假 假
//当有一个表达式不成立,那么整个表达式不成立
//int main(int argc, const char *argv[])
//{
// int a = 0,b=20;
//
// printf("a&&b = %d\n",a&&b);
//
// return 0;
//}
//||逻辑或
// 表达式1
表达式2 ... 表达式
// 真
真 真
// 假
真 真
// 真
假 真
// 假
假 假
//当有一个表达式为真,则整个表达式为真
//int main(int argc, const char *argv[])
//{
// int a=0,b=0;
//
// printf("a||b = %d\n", a||b);
//
// return 0;
//}
//条件运算符: ? :
//三目运算符
//表达式?表达式1:表达式2
//先判断表达式是否成立,成立整个表达式的值就是表达式1的值,反之是表达式2的值
//int main(int argc, const char *argv[])
//{
// int a= 30, b = 20;
// printf("max(a,b) = %d\n", a>b?a:b);
// printf("min(a,b) = %d\n", a>b?b:a);
// return 0;
//}
//赋值运算符: = /= *= %= += -=
//int main(int argc, const char *argv[])
//{
// int a=40;
// int b=4;
// //b = 50;
// printf("a= %d\n",a/=2);//a = a/2;
// a = 40;
// printf("a*=b = %d\n",a*=b);//a=a*b;
// a = 40;
// printf("a/=b = %d\n",a/=b);//a=a/b;
// a =40;
// printf("a%%=b = %d\n",a%=b);//a=a%b;
//
// a =40;
// printf("a+=b = %d\n", a+=b);//a= a+b;
//
// a= 40;
// printf("a-=b = %d\n", a-=b);//a=a-b;
// //printf("%d %d\n", a+=b,a-=b);//a的值未定义
// return 0;
//}
//逗号运算符: ,
//表达式1,表达式2,表达式3,表达式4,.....表达式n
//逗号表达式的值是表达式n的值
//int main(int argc, const char *argv[])
//{
// int a=10,b=20,c=30,d=40;
// //int f = 0;
// int e;
//// e=a+b,c+d;
// printf("%d\n",(e=a+b,c+d));
// printf("%d\n",(e=c+d,a+b));
//
// return 0;
//}
//运算符优先级
//括号 >
单目运算符 > 算术运算符(/ * % > + -) >关系运算符 >逻辑运算符 (&& > ||)
>三目运算符 >
赋值运算符 >逗号运算符
//采用加括号的方式提高优先级
//类型转换
//
//int a=5 + char b=6
// 0000 0000 0000 0000 0000 0000 0000 0101
// + 0000 0000 0000 0000 0000 0000 0000 0110 //位扩展
//-----------------------------------------------
// 0000 0000 0000 0000 0000 0000 0000 1011 = 11
// int a=5 char b=-6
// 0000 0000 0000 0000 0000 0000 0000 0101
// 1111 1111 1111 1111 1111 1111 1111 1010 //补1
//--------------------------------------------
// 1111 1111 1111 1111 1111 1111 1111 1111 = -1
//int main(int argc, const char *argv[])
//{
// int a=5;
// char b = 6;
// printf("%d\n",a+b);//
位扩展 发生隐式转换
//
//
// int c= 0x123350; //位截断
// short d;
// d = c;
//
// printf("d=0x%x\n",d);
// return 0;
//}
//1.整型数据之间运算,
当有long long 其它类型的数据向long long看齐
//2.没有 long long有long类型其它类型向long类型看齐
//3.既没有long long也没有long 有int类型数据,其它类型数据向int类型数据看齐
//4. 只有char short类型向 int类型数据看齐
//5. 有浮点类型数据的时候,向浮点类型数据看齐(整型转浮点类型)
//6. float double 向 long double看齐
//7. 没有long double有double向double看齐
//8. 有符号类型向无符号类型数据看齐
//int main(int argc, const char *argv[])
//{
// int a=10;
// float f=3.45;
//
// printf("%f\n",a+f);//隐式转换
// printf("%d\n",(int)(a+f));//强制转化
// return 0;
//}
//0000 0000 0000 0000 0000 0000 0000 0101
//1111 1111 1111 1111 1111 1111 1111 1010
//------------------------------------------
//
//int main(int argc,const char *argv[])
//{
// unsigned int a = 5;
// char b = -6;
//
// printf("%d\n",a+b);
//
// return 0;
//}
//control + i //排序代码
//int main(int argc, const char *argv[])
//{
// char a;
// int b = 0x56756;
// a = b;//截断
// printf("%d %ld\n",a,sizeof(a));
//
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// int a = 256;//0000 0000 0000 0000 00000 10000 0000
// char b;
// b = a;
// printf("%d\n",b);
// return 0;
//}
//511 /16 15
//31 /16 15
//1 /16 1
////0x1ff
//int main(int argc,const char *argv[])
//{
// int a = 511;
// char b;
// b = a; //1111 1111
// printf("%d\n",b);
// return 0;
//}
//int main(int argc, const char *argv[])
//{
// int a;
// float b = 3.14;
// a = b;
// printf("%d\n",a);
// return 0;
//}
int main(int argc,constchar *argv[])
{
float a =3.14;
int b;
b = (int)a%2;
printf("%d\n",b);
return 0;
}
相关文章推荐
- leetcode笔记--Swap Nodes in Pairs
- linux文件去重
- c注释转换成c++注释
- SimpleFolderEncrypt使用帮助
- IOS 支付完成回退到指定界面
- 深入理解Java:注解(Annotation)--注解处理器
- android下拉刷新和滑动到底部加载更多,自定义listview
- cordova环境配置以及简单例子创建
- c语言中变量前的static的作用
- dyld: Library not loaded: @rpath/libswiftAVFoundation.dylib
- AngularJs+bootstrap搭载前台框架――基础页面
- linux 下实用的命令
- 使用ipython %matplotlib inline
- VS013添加ConfigurationManager类引用方法
- svn import时候出现问题
- Linux禁止root账户远程登录
- 解决Mac下Android SDK Manager联网失败的问题?
- 简洁的语言和逻辑
- 结束指定activity
- 同步参数介绍