一.一些代码及分析

(1)

#include<stdio.h>
int main()
{
short s = 0;
int a = 10;
printf("%d\n", sizeof(s = a + 5));
printf("%d\n", s);
return 0;
}

这个代码的运行结果是什么呢?答案是:2 0

分析:首先看第一个printf,a+5是一个整型为4个字节,s为短整型为2个字节,所以将a+5放入s中会转化为短整型,为2个字节大小,所以第一个打印2。

看第二个printf,由于sizeof中放的表达式不会真实进行运算,故s仍为0,所以第二个打印0。

(2)

int main()
{
int a = 0;
printf("%d\n",~a);
return 0;
}

这个代码的运行结果是什么呢?答案是: -1

分析:~是按(二进制)位取反,由于0的二进制补码为

00000000000000000000000000000000(储存在内存中的是补码,~对补码进行操作)

111111111111111111111111111111111111(按位取反,还是补码)

111111111111111111111111111111111110(反码)

10000000000000000000000000000001(原码,打印出的是原码,所以转化为原码)

结果为:-1(将原码转化为10进制,第一位为1所以为-,最后一位为1*10^0)

(3)

void test1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(ch));
test1(arr);
test2(ch);
return 0;
}

这个代码的运行结果是什么呢?答案是: 40 10  4  4

分析:第13行的打印,sizeof(arr)是计算arr数组的大小,由于int为整形是4个字节,又由于有10个元素,所以打印出40。第14行的打印,sizeof(ch),因为char为1个字节,有10个元素,所以打印10。第15行的打印,由于传入test1的为arr首元素的地址,故用指针接收,又指针为4或8(32位为4,64位为8),所以打印4;第16行同上,打印4。

(4)360笔试题

int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a=%d\n b=%d\n c=%d\n d=%d\n", a, b, c, d);
return 0;
}

这个代码的运行结果是什么呢?答案是:a=1 b=2 c=3 d=4

分析:a++&&++b,由于a++先执行后++,所以a++开始时为0,所以0&&++b&&d++为0,因为a++为0,且后边都是&&,所以后边不用执行,i=0。所以最终只执行了a++,所以a=1,其他没变化。所以打印a=1 b=2 c=3 d=4。

将代码变化一下

int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("a=%d\n b=%d\n c=%d\n d=%d\n", a, b, c, d);
return 0;
}

这个代码的运行结果是什么呢?答案是:1 3 3 4

分析:a++ || ++b,因为a++为0,++b为3,又 i = a++ || ++b || d++,所以执行到++b(因为++b为真整体为真,后面不再执行),所以只执行了a++,++b。所以最后打印a=1 b=3 c=3 d=4。

二.逗号表达式(从左向右依次执行。整个表达式的结果是最后一个表达式的结果。)

代码1,问:c是多少

int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
return 0;
}

答案是:13

分析:从左向右依次执行,a>b执行一次,a=b+10执行一次(a=12),a执行一次,b=a+1执行一次(b=13),故打印13

代码2

if(a=b+1,c=a/2,d>0)

三.下标引用、函数调用和结构成员

1.[]下标引用操作符

​操作数:一个数组名+一个索引值

int main()
{
int arr[10];//创建数组
arr[9] = 10;//使用下标引用操作符
return 0;
}

[]的两个操作数为arr和9。

2.函数调用操作符,接受一个或多个操作数:第一个操作数是函数名,剩余的操作数是传递给函数的参数。

3.结构成员

//创建一个结构体类型struct stu
struct stu
{
//成员变量
char name[20];
int age;
char id[20];
};
void main()
{
int a = 10;
//使用struct stu这个类型创建一个学生对象s1,并初始化
struct stu s1 = { "张三",20,"2019010305" };
printf("%s\n", s1.name);
printf("%d\n", s1.age);
printf("%s\n", s1.id);
//结构体变量.成员名
}

使用指针来操作

//创建一个结构体类型struct stu
struct stu
{
//成员变量
char name[20];
int age;
char id[20];
};
void main()
{
int a = 10;
//使用struct stu这个类型创建一个学生对象s1,并初始化
struct stu s1 = { "张三",20,"2019010305" };
struct stu* p = &s1;
printf("%s\n", p->name);
printf("%d\n", p->age);
}

四.隐式类型转换

(1)整型提升

​表达式中的字符和短整型操作数在使用之前被转化为普通整型,这种转化称为整型提升(CPU内整型运算器(ALU)的操作数的字节长度一般是int的字节长度,同时也是CPU的通用寄存器的长度。所以表达式中各种长度可能小于int长度的整型值,都必须先转化为int或unsigned int,然后才能送去CPU执行运算)

代码1

void main()
{
char a = 3;
//00000000000000000000000000000011
//00000011 -a(char为一个字节,所以从后边截断一个字节)

char b = 127;
//00000000000000000000000001111111
//01111111 -b

//a和b如何相加
//00000000000000000000000000000011
//00000000000000000000000001111111
//00000000000000000000000010000010

char c = a + b;
//10000010 -c
//11111111111111111111111110000010 -补码
//11111111111111111111111110000001 -反码
//100000000000000000000001111110 -原码
//-126

printf("%d\n", c);
}

a与b的值被提升为普通整型,然后再执行加法运算。加法运算后,结果将被截断,再储存在c中

如何进行整形提升?c语言琐碎知识(主要是分析代码)_数组

代码2

void main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(!c));
}

分析:c只要参与表达式运算,就会发生整形提升,表达式+c会发生整型提升,所以sizeof(+c)是4个字节。所以结果为:1 4 1

(2)算术转化c语言琐碎知识(主要是分析代码)_补码_02